• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/v8.h"
6 
7 #include "src/execution.h"
8 #include "src/handles.h"
9 #include "src/interpreter/bytecode-array-builder.h"
10 #include "src/interpreter/bytecode-array-iterator.h"
11 #include "src/interpreter/bytecode-label.h"
12 #include "src/interpreter/interpreter.h"
13 #include "test/cctest/cctest.h"
14 #include "test/cctest/interpreter/interpreter-tester.h"
15 #include "test/cctest/test-feedback-vector.h"
16 
17 namespace v8 {
18 namespace internal {
19 namespace interpreter {
20 
21 
TEST(InterpreterReturn)22 TEST(InterpreterReturn) {
23   HandleAndZoneScope handles;
24   Handle<Object> undefined_value =
25       handles.main_isolate()->factory()->undefined_value();
26 
27   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
28                                0, 0);
29   builder.Return();
30   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
31 
32   InterpreterTester tester(handles.main_isolate(), bytecode_array);
33   auto callable = tester.GetCallable<>();
34   Handle<Object> return_val = callable().ToHandleChecked();
35   CHECK(return_val.is_identical_to(undefined_value));
36 }
37 
38 
TEST(InterpreterLoadUndefined)39 TEST(InterpreterLoadUndefined) {
40   HandleAndZoneScope handles;
41   Handle<Object> undefined_value =
42       handles.main_isolate()->factory()->undefined_value();
43 
44   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
45                                0, 0);
46   builder.LoadUndefined().Return();
47   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
48 
49   InterpreterTester tester(handles.main_isolate(), bytecode_array);
50   auto callable = tester.GetCallable<>();
51   Handle<Object> return_val = callable().ToHandleChecked();
52   CHECK(return_val.is_identical_to(undefined_value));
53 }
54 
55 
TEST(InterpreterLoadNull)56 TEST(InterpreterLoadNull) {
57   HandleAndZoneScope handles;
58   Handle<Object> null_value = handles.main_isolate()->factory()->null_value();
59 
60   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
61                                0, 0);
62   builder.LoadNull().Return();
63   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
64 
65   InterpreterTester tester(handles.main_isolate(), bytecode_array);
66   auto callable = tester.GetCallable<>();
67   Handle<Object> return_val = callable().ToHandleChecked();
68   CHECK(return_val.is_identical_to(null_value));
69 }
70 
71 
TEST(InterpreterLoadTheHole)72 TEST(InterpreterLoadTheHole) {
73   HandleAndZoneScope handles;
74   Handle<Object> the_hole_value =
75       handles.main_isolate()->factory()->the_hole_value();
76 
77   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
78                                0, 0);
79   builder.LoadTheHole().Return();
80   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
81 
82   InterpreterTester tester(handles.main_isolate(), bytecode_array);
83   auto callable = tester.GetCallable<>();
84   Handle<Object> return_val = callable().ToHandleChecked();
85   CHECK(return_val.is_identical_to(the_hole_value));
86 }
87 
88 
TEST(InterpreterLoadTrue)89 TEST(InterpreterLoadTrue) {
90   HandleAndZoneScope handles;
91   Handle<Object> true_value = handles.main_isolate()->factory()->true_value();
92 
93   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
94                                0, 0);
95   builder.LoadTrue().Return();
96   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
97 
98   InterpreterTester tester(handles.main_isolate(), bytecode_array);
99   auto callable = tester.GetCallable<>();
100   Handle<Object> return_val = callable().ToHandleChecked();
101   CHECK(return_val.is_identical_to(true_value));
102 }
103 
104 
TEST(InterpreterLoadFalse)105 TEST(InterpreterLoadFalse) {
106   HandleAndZoneScope handles;
107   Handle<Object> false_value = handles.main_isolate()->factory()->false_value();
108 
109   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
110                                0, 0);
111   builder.LoadFalse().Return();
112   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
113 
114   InterpreterTester tester(handles.main_isolate(), bytecode_array);
115   auto callable = tester.GetCallable<>();
116   Handle<Object> return_val = callable().ToHandleChecked();
117   CHECK(return_val.is_identical_to(false_value));
118 }
119 
120 
TEST(InterpreterLoadLiteral)121 TEST(InterpreterLoadLiteral) {
122   HandleAndZoneScope handles;
123   i::Factory* factory = handles.main_isolate()->factory();
124 
125   // Small Smis.
126   for (int i = -128; i < 128; i++) {
127     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
128                                  0, 0);
129     builder.LoadLiteral(Smi::FromInt(i)).Return();
130     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
131 
132     InterpreterTester tester(handles.main_isolate(), bytecode_array);
133     auto callable = tester.GetCallable<>();
134     Handle<Object> return_val = callable().ToHandleChecked();
135     CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(i));
136   }
137 
138   // Large Smis.
139   {
140     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
141                                  0, 0);
142 
143     builder.LoadLiteral(Smi::FromInt(0x12345678)).Return();
144     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
145 
146     InterpreterTester tester(handles.main_isolate(), bytecode_array);
147     auto callable = tester.GetCallable<>();
148     Handle<Object> return_val = callable().ToHandleChecked();
149     CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(0x12345678));
150   }
151 
152   // Heap numbers.
153   {
154     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
155                                  0, 0);
156 
157     builder.LoadLiteral(factory->NewHeapNumber(-2.1e19)).Return();
158     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
159 
160     InterpreterTester tester(handles.main_isolate(), bytecode_array);
161     auto callable = tester.GetCallable<>();
162     Handle<Object> return_val = callable().ToHandleChecked();
163     CHECK_EQ(i::HeapNumber::cast(*return_val)->value(), -2.1e19);
164   }
165 
166   // Strings.
167   {
168     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
169                                  0, 0);
170 
171     Handle<i::String> string = factory->NewStringFromAsciiChecked("String");
172     builder.LoadLiteral(string).Return();
173     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
174 
175     InterpreterTester tester(handles.main_isolate(), bytecode_array);
176     auto callable = tester.GetCallable<>();
177     Handle<Object> return_val = callable().ToHandleChecked();
178     CHECK(i::String::cast(*return_val)->Equals(*string));
179   }
180 }
181 
182 
TEST(InterpreterLoadStoreRegisters)183 TEST(InterpreterLoadStoreRegisters) {
184   HandleAndZoneScope handles;
185   Handle<Object> true_value = handles.main_isolate()->factory()->true_value();
186   for (int i = 0; i <= kMaxInt8; i++) {
187     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
188                                  0, i + 1);
189 
190     Register reg(i);
191     builder.LoadTrue()
192         .StoreAccumulatorInRegister(reg)
193         .LoadFalse()
194         .LoadAccumulatorWithRegister(reg)
195         .Return();
196     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
197 
198     InterpreterTester tester(handles.main_isolate(), bytecode_array);
199     auto callable = tester.GetCallable<>();
200     Handle<Object> return_val = callable().ToHandleChecked();
201     CHECK(return_val.is_identical_to(true_value));
202   }
203 }
204 
205 
206 static const Token::Value kShiftOperators[] = {
207     Token::Value::SHL, Token::Value::SAR, Token::Value::SHR};
208 
209 
210 static const Token::Value kArithmeticOperators[] = {
211     Token::Value::BIT_OR, Token::Value::BIT_XOR, Token::Value::BIT_AND,
212     Token::Value::SHL,    Token::Value::SAR,     Token::Value::SHR,
213     Token::Value::ADD,    Token::Value::SUB,     Token::Value::MUL,
214     Token::Value::DIV,    Token::Value::MOD};
215 
216 
BinaryOpC(Token::Value op,double lhs,double rhs)217 static double BinaryOpC(Token::Value op, double lhs, double rhs) {
218   switch (op) {
219     case Token::Value::ADD:
220       return lhs + rhs;
221     case Token::Value::SUB:
222       return lhs - rhs;
223     case Token::Value::MUL:
224       return lhs * rhs;
225     case Token::Value::DIV:
226       return lhs / rhs;
227     case Token::Value::MOD:
228       return std::fmod(lhs, rhs);
229     case Token::Value::BIT_OR:
230       return (v8::internal::DoubleToInt32(lhs) |
231               v8::internal::DoubleToInt32(rhs));
232     case Token::Value::BIT_XOR:
233       return (v8::internal::DoubleToInt32(lhs) ^
234               v8::internal::DoubleToInt32(rhs));
235     case Token::Value::BIT_AND:
236       return (v8::internal::DoubleToInt32(lhs) &
237               v8::internal::DoubleToInt32(rhs));
238     case Token::Value::SHL: {
239       int32_t val = v8::internal::DoubleToInt32(lhs);
240       uint32_t count = v8::internal::DoubleToUint32(rhs) & 0x1F;
241       int32_t result = val << count;
242       return result;
243     }
244     case Token::Value::SAR: {
245       int32_t val = v8::internal::DoubleToInt32(lhs);
246       uint32_t count = v8::internal::DoubleToUint32(rhs) & 0x1F;
247       int32_t result = val >> count;
248       return result;
249     }
250     case Token::Value::SHR: {
251       uint32_t val = v8::internal::DoubleToUint32(lhs);
252       uint32_t count = v8::internal::DoubleToUint32(rhs) & 0x1F;
253       uint32_t result = val >> count;
254       return result;
255     }
256     default:
257       UNREACHABLE();
258       return std::numeric_limits<double>::min();
259   }
260 }
261 
262 
TEST(InterpreterShiftOpsSmi)263 TEST(InterpreterShiftOpsSmi) {
264   int lhs_inputs[] = {0, -17, -182, 1073741823, -1};
265   int rhs_inputs[] = {5, 2, 1, -1, -2, 0, 31, 32, -32, 64, 37};
266   for (size_t l = 0; l < arraysize(lhs_inputs); l++) {
267     for (size_t r = 0; r < arraysize(rhs_inputs); r++) {
268       for (size_t o = 0; o < arraysize(kShiftOperators); o++) {
269         HandleAndZoneScope handles;
270         i::Factory* factory = handles.main_isolate()->factory();
271         BytecodeArrayBuilder builder(handles.main_isolate(),
272                                      handles.main_zone(), 1, 0, 1);
273         Register reg(0);
274         int lhs = lhs_inputs[l];
275         int rhs = rhs_inputs[r];
276         builder.LoadLiteral(Smi::FromInt(lhs))
277             .StoreAccumulatorInRegister(reg)
278             .LoadLiteral(Smi::FromInt(rhs))
279             .BinaryOperation(kShiftOperators[o], reg)
280             .Return();
281         Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
282 
283         InterpreterTester tester(handles.main_isolate(), bytecode_array);
284         auto callable = tester.GetCallable<>();
285         Handle<Object> return_value = callable().ToHandleChecked();
286         Handle<Object> expected_value =
287             factory->NewNumber(BinaryOpC(kShiftOperators[o], lhs, rhs));
288         CHECK(return_value->SameValue(*expected_value));
289       }
290     }
291   }
292 }
293 
294 
TEST(InterpreterBinaryOpsSmi)295 TEST(InterpreterBinaryOpsSmi) {
296   int lhs_inputs[] = {3266, 1024, 0, -17, -18000};
297   int rhs_inputs[] = {3266, 5, 4, 3, 2, 1, -1, -2};
298   for (size_t l = 0; l < arraysize(lhs_inputs); l++) {
299     for (size_t r = 0; r < arraysize(rhs_inputs); r++) {
300       for (size_t o = 0; o < arraysize(kArithmeticOperators); o++) {
301         HandleAndZoneScope handles;
302         i::Factory* factory = handles.main_isolate()->factory();
303         BytecodeArrayBuilder builder(handles.main_isolate(),
304                                      handles.main_zone(), 1, 0, 1);
305 
306         Register reg(0);
307         int lhs = lhs_inputs[l];
308         int rhs = rhs_inputs[r];
309         builder.LoadLiteral(Smi::FromInt(lhs))
310             .StoreAccumulatorInRegister(reg)
311             .LoadLiteral(Smi::FromInt(rhs))
312             .BinaryOperation(kArithmeticOperators[o], reg)
313             .Return();
314         Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
315 
316         InterpreterTester tester(handles.main_isolate(), bytecode_array);
317         auto callable = tester.GetCallable<>();
318         Handle<Object> return_value = callable().ToHandleChecked();
319         Handle<Object> expected_value =
320             factory->NewNumber(BinaryOpC(kArithmeticOperators[o], lhs, rhs));
321         CHECK(return_value->SameValue(*expected_value));
322       }
323     }
324   }
325 }
326 
327 
TEST(InterpreterBinaryOpsHeapNumber)328 TEST(InterpreterBinaryOpsHeapNumber) {
329   double lhs_inputs[] = {3266.101, 1024.12, 0.01, -17.99, -18000.833, 9.1e17};
330   double rhs_inputs[] = {3266.101, 5.999, 4.778, 3.331,  2.643,
331                          1.1,      -1.8,  -2.9,  8.3e-27};
332   for (size_t l = 0; l < arraysize(lhs_inputs); l++) {
333     for (size_t r = 0; r < arraysize(rhs_inputs); r++) {
334       for (size_t o = 0; o < arraysize(kArithmeticOperators); o++) {
335         HandleAndZoneScope handles;
336         i::Factory* factory = handles.main_isolate()->factory();
337         BytecodeArrayBuilder builder(handles.main_isolate(),
338                                      handles.main_zone(), 1, 0, 1);
339         Register reg(0);
340         double lhs = lhs_inputs[l];
341         double rhs = rhs_inputs[r];
342         builder.LoadLiteral(factory->NewNumber(lhs))
343             .StoreAccumulatorInRegister(reg)
344             .LoadLiteral(factory->NewNumber(rhs))
345             .BinaryOperation(kArithmeticOperators[o], reg)
346             .Return();
347         Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
348 
349         InterpreterTester tester(handles.main_isolate(), bytecode_array);
350         auto callable = tester.GetCallable<>();
351         Handle<Object> return_value = callable().ToHandleChecked();
352         Handle<Object> expected_value =
353             factory->NewNumber(BinaryOpC(kArithmeticOperators[o], lhs, rhs));
354         CHECK(return_value->SameValue(*expected_value));
355       }
356     }
357   }
358 }
359 
360 
TEST(InterpreterStringAdd)361 TEST(InterpreterStringAdd) {
362   HandleAndZoneScope handles;
363   i::Factory* factory = handles.main_isolate()->factory();
364 
365   struct TestCase {
366     Handle<Object> lhs;
367     Handle<Object> rhs;
368     Handle<Object> expected_value;
369   } test_cases[] = {
370       {factory->NewStringFromStaticChars("a"),
371        factory->NewStringFromStaticChars("b"),
372        factory->NewStringFromStaticChars("ab")},
373       {factory->NewStringFromStaticChars("aaaaaa"),
374        factory->NewStringFromStaticChars("b"),
375        factory->NewStringFromStaticChars("aaaaaab")},
376       {factory->NewStringFromStaticChars("aaa"),
377        factory->NewStringFromStaticChars("bbbbb"),
378        factory->NewStringFromStaticChars("aaabbbbb")},
379       {factory->NewStringFromStaticChars(""),
380        factory->NewStringFromStaticChars("b"),
381        factory->NewStringFromStaticChars("b")},
382       {factory->NewStringFromStaticChars("a"),
383        factory->NewStringFromStaticChars(""),
384        factory->NewStringFromStaticChars("a")},
385       {factory->NewStringFromStaticChars("1.11"), factory->NewHeapNumber(2.5),
386        factory->NewStringFromStaticChars("1.112.5")},
387       {factory->NewStringFromStaticChars("-1.11"), factory->NewHeapNumber(2.56),
388        factory->NewStringFromStaticChars("-1.112.56")},
389       {factory->NewStringFromStaticChars(""), factory->NewHeapNumber(2.5),
390        factory->NewStringFromStaticChars("2.5")},
391   };
392 
393   for (size_t i = 0; i < arraysize(test_cases); i++) {
394     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
395                                  0, 1);
396 
397     Register reg(0);
398     builder.LoadLiteral(test_cases[i].lhs)
399         .StoreAccumulatorInRegister(reg)
400         .LoadLiteral(test_cases[i].rhs)
401         .BinaryOperation(Token::Value::ADD, reg)
402         .Return();
403     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
404 
405     InterpreterTester tester(handles.main_isolate(), bytecode_array);
406     auto callable = tester.GetCallable<>();
407     Handle<Object> return_value = callable().ToHandleChecked();
408     CHECK(return_value->SameValue(*test_cases[i].expected_value));
409   }
410 }
411 
412 
TEST(InterpreterParameter1)413 TEST(InterpreterParameter1) {
414   HandleAndZoneScope handles;
415   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
416                                0, 0);
417 
418   builder.LoadAccumulatorWithRegister(builder.Parameter(0)).Return();
419   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
420 
421   InterpreterTester tester(handles.main_isolate(), bytecode_array);
422   auto callable = tester.GetCallable<Handle<Object>>();
423 
424   // Check for heap objects.
425   Handle<Object> true_value = handles.main_isolate()->factory()->true_value();
426   Handle<Object> return_val = callable(true_value).ToHandleChecked();
427   CHECK(return_val.is_identical_to(true_value));
428 
429   // Check for Smis.
430   return_val = callable(Handle<Smi>(Smi::FromInt(3), handles.main_isolate()))
431                    .ToHandleChecked();
432   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(3));
433 }
434 
435 
TEST(InterpreterParameter8)436 TEST(InterpreterParameter8) {
437   HandleAndZoneScope handles;
438   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 8,
439                                0, 0);
440 
441   builder.LoadAccumulatorWithRegister(builder.Parameter(0))
442       .BinaryOperation(Token::Value::ADD, builder.Parameter(1))
443       .BinaryOperation(Token::Value::ADD, builder.Parameter(2))
444       .BinaryOperation(Token::Value::ADD, builder.Parameter(3))
445       .BinaryOperation(Token::Value::ADD, builder.Parameter(4))
446       .BinaryOperation(Token::Value::ADD, builder.Parameter(5))
447       .BinaryOperation(Token::Value::ADD, builder.Parameter(6))
448       .BinaryOperation(Token::Value::ADD, builder.Parameter(7))
449       .Return();
450   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
451 
452   InterpreterTester tester(handles.main_isolate(), bytecode_array);
453   typedef Handle<Object> H;
454   auto callable = tester.GetCallable<H, H, H, H, H, H, H, H>();
455 
456   Handle<Smi> arg1 = Handle<Smi>(Smi::FromInt(1), handles.main_isolate());
457   Handle<Smi> arg2 = Handle<Smi>(Smi::FromInt(2), handles.main_isolate());
458   Handle<Smi> arg3 = Handle<Smi>(Smi::FromInt(3), handles.main_isolate());
459   Handle<Smi> arg4 = Handle<Smi>(Smi::FromInt(4), handles.main_isolate());
460   Handle<Smi> arg5 = Handle<Smi>(Smi::FromInt(5), handles.main_isolate());
461   Handle<Smi> arg6 = Handle<Smi>(Smi::FromInt(6), handles.main_isolate());
462   Handle<Smi> arg7 = Handle<Smi>(Smi::FromInt(7), handles.main_isolate());
463   Handle<Smi> arg8 = Handle<Smi>(Smi::FromInt(8), handles.main_isolate());
464   // Check for Smis.
465   Handle<Object> return_val =
466       callable(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
467           .ToHandleChecked();
468   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(36));
469 }
470 
471 
TEST(InterpreterParameter1Assign)472 TEST(InterpreterParameter1Assign) {
473   HandleAndZoneScope handles;
474   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
475                                0, 0);
476 
477   builder.LoadLiteral(Smi::FromInt(5))
478       .StoreAccumulatorInRegister(builder.Parameter(0))
479       .LoadAccumulatorWithRegister(builder.Parameter(0))
480       .Return();
481   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
482 
483   InterpreterTester tester(handles.main_isolate(), bytecode_array);
484   auto callable = tester.GetCallable<Handle<Object>>();
485 
486   Handle<Object> return_val =
487       callable(Handle<Smi>(Smi::FromInt(3), handles.main_isolate()))
488           .ToHandleChecked();
489   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(5));
490 }
491 
492 
TEST(InterpreterLoadGlobal)493 TEST(InterpreterLoadGlobal) {
494   HandleAndZoneScope handles;
495 
496   // Test loading a global.
497   std::string source(
498       "var global = 321;\n"
499       "function " + InterpreterTester::function_name() + "() {\n"
500       "  return global;\n"
501       "}");
502   InterpreterTester tester(handles.main_isolate(), source.c_str());
503   auto callable = tester.GetCallable<>();
504 
505   Handle<Object> return_val = callable().ToHandleChecked();
506   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(321));
507 }
508 
509 
TEST(InterpreterStoreGlobal)510 TEST(InterpreterStoreGlobal) {
511   HandleAndZoneScope handles;
512   i::Isolate* isolate = handles.main_isolate();
513   i::Factory* factory = isolate->factory();
514 
515   // Test storing to a global.
516   std::string source(
517       "var global = 321;\n"
518       "function " + InterpreterTester::function_name() + "() {\n"
519       "  global = 999;\n"
520       "}");
521   InterpreterTester tester(handles.main_isolate(), source.c_str());
522   auto callable = tester.GetCallable<>();
523 
524   callable().ToHandleChecked();
525   Handle<i::String> name = factory->InternalizeUtf8String("global");
526   Handle<i::Object> global_obj =
527       Object::GetProperty(isolate->global_object(), name).ToHandleChecked();
528   CHECK_EQ(Smi::cast(*global_obj), Smi::FromInt(999));
529 }
530 
531 
TEST(InterpreterCallGlobal)532 TEST(InterpreterCallGlobal) {
533   HandleAndZoneScope handles;
534 
535   // Test calling a global function.
536   std::string source(
537       "function g_add(a, b) { return a + b; }\n"
538       "function " + InterpreterTester::function_name() + "() {\n"
539       "  return g_add(5, 10);\n"
540       "}");
541   InterpreterTester tester(handles.main_isolate(), source.c_str());
542   auto callable = tester.GetCallable<>();
543 
544   Handle<Object> return_val = callable().ToHandleChecked();
545   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(15));
546 }
547 
548 
TEST(InterpreterLoadUnallocated)549 TEST(InterpreterLoadUnallocated) {
550   HandleAndZoneScope handles;
551 
552   // Test loading an unallocated global.
553   std::string source(
554       "unallocated = 123;\n"
555       "function " + InterpreterTester::function_name() + "() {\n"
556       "  return unallocated;\n"
557       "}");
558   InterpreterTester tester(handles.main_isolate(), source.c_str());
559   auto callable = tester.GetCallable<>();
560 
561   Handle<Object> return_val = callable().ToHandleChecked();
562   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(123));
563 }
564 
565 
TEST(InterpreterStoreUnallocated)566 TEST(InterpreterStoreUnallocated) {
567   HandleAndZoneScope handles;
568   i::Isolate* isolate = handles.main_isolate();
569   i::Factory* factory = isolate->factory();
570 
571   // Test storing to an unallocated global.
572   std::string source(
573       "unallocated = 321;\n"
574       "function " + InterpreterTester::function_name() + "() {\n"
575       "  unallocated = 999;\n"
576       "}");
577   InterpreterTester tester(handles.main_isolate(), source.c_str());
578   auto callable = tester.GetCallable<>();
579 
580   callable().ToHandleChecked();
581   Handle<i::String> name = factory->InternalizeUtf8String("unallocated");
582   Handle<i::Object> global_obj =
583       Object::GetProperty(isolate->global_object(), name).ToHandleChecked();
584   CHECK_EQ(Smi::cast(*global_obj), Smi::FromInt(999));
585 }
586 
587 
TEST(InterpreterLoadNamedProperty)588 TEST(InterpreterLoadNamedProperty) {
589   HandleAndZoneScope handles;
590   i::Isolate* isolate = handles.main_isolate();
591   i::Factory* factory = isolate->factory();
592   i::Zone zone(isolate->allocator());
593 
594   i::FeedbackVectorSpec feedback_spec(&zone);
595   i::FeedbackVectorSlot slot = feedback_spec.AddLoadICSlot();
596 
597   Handle<i::TypeFeedbackVector> vector =
598       i::NewTypeFeedbackVector(isolate, &feedback_spec);
599 
600   Handle<i::String> name = factory->NewStringFromAsciiChecked("val");
601   name = factory->string_table()->LookupString(isolate, name);
602 
603   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
604                                0, 0);
605 
606   builder.LoadNamedProperty(builder.Parameter(0), name, vector->GetIndex(slot))
607       .Return();
608   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
609 
610   InterpreterTester tester(handles.main_isolate(), bytecode_array, vector);
611   auto callable = tester.GetCallable<Handle<Object>>();
612 
613   Handle<Object> object = InterpreterTester::NewObject("({ val : 123 })");
614   // Test IC miss.
615   Handle<Object> return_val = callable(object).ToHandleChecked();
616   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(123));
617 
618   // Test transition to monomorphic IC.
619   return_val = callable(object).ToHandleChecked();
620   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(123));
621 
622   // Test transition to polymorphic IC.
623   Handle<Object> object2 =
624       InterpreterTester::NewObject("({ val : 456, other : 123 })");
625   return_val = callable(object2).ToHandleChecked();
626   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(456));
627 
628   // Test transition to megamorphic IC.
629   Handle<Object> object3 =
630       InterpreterTester::NewObject("({ val : 789, val2 : 123 })");
631   callable(object3).ToHandleChecked();
632   Handle<Object> object4 =
633       InterpreterTester::NewObject("({ val : 789, val3 : 123 })");
634   callable(object4).ToHandleChecked();
635   Handle<Object> object5 =
636       InterpreterTester::NewObject("({ val : 789, val4 : 123 })");
637   return_val = callable(object5).ToHandleChecked();
638   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(789));
639 }
640 
641 
TEST(InterpreterLoadKeyedProperty)642 TEST(InterpreterLoadKeyedProperty) {
643   HandleAndZoneScope handles;
644   i::Isolate* isolate = handles.main_isolate();
645   i::Factory* factory = isolate->factory();
646   i::Zone zone(isolate->allocator());
647 
648   i::FeedbackVectorSpec feedback_spec(&zone);
649   i::FeedbackVectorSlot slot = feedback_spec.AddKeyedLoadICSlot();
650 
651   Handle<i::TypeFeedbackVector> vector =
652       i::NewTypeFeedbackVector(isolate, &feedback_spec);
653 
654   Handle<i::String> key = factory->NewStringFromAsciiChecked("key");
655   key = factory->string_table()->LookupString(isolate, key);
656 
657   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
658                                0, 1);
659 
660   builder.LoadLiteral(key)
661       .LoadKeyedProperty(builder.Parameter(0), vector->GetIndex(slot))
662       .Return();
663   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
664 
665   InterpreterTester tester(handles.main_isolate(), bytecode_array, vector);
666   auto callable = tester.GetCallable<Handle<Object>>();
667 
668   Handle<Object> object = InterpreterTester::NewObject("({ key : 123 })");
669   // Test IC miss.
670   Handle<Object> return_val = callable(object).ToHandleChecked();
671   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(123));
672 
673   // Test transition to monomorphic IC.
674   return_val = callable(object).ToHandleChecked();
675   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(123));
676 
677   // Test transition to megamorphic IC.
678   Handle<Object> object3 =
679       InterpreterTester::NewObject("({ key : 789, val2 : 123 })");
680   return_val = callable(object3).ToHandleChecked();
681   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(789));
682 }
683 
684 
TEST(InterpreterStoreNamedProperty)685 TEST(InterpreterStoreNamedProperty) {
686   HandleAndZoneScope handles;
687   i::Isolate* isolate = handles.main_isolate();
688   i::Factory* factory = isolate->factory();
689   i::Zone zone(isolate->allocator());
690 
691   i::FeedbackVectorSpec feedback_spec(&zone);
692   i::FeedbackVectorSlot slot = feedback_spec.AddStoreICSlot();
693 
694   Handle<i::TypeFeedbackVector> vector =
695       i::NewTypeFeedbackVector(isolate, &feedback_spec);
696 
697   Handle<i::String> name = factory->NewStringFromAsciiChecked("val");
698   name = factory->string_table()->LookupString(isolate, name);
699 
700   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
701                                0, 0);
702 
703   builder.LoadLiteral(Smi::FromInt(999))
704       .StoreNamedProperty(builder.Parameter(0), name, vector->GetIndex(slot),
705                           i::STRICT)
706       .Return();
707   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
708 
709   InterpreterTester tester(isolate, bytecode_array, vector);
710   auto callable = tester.GetCallable<Handle<Object>>();
711   Handle<Object> object = InterpreterTester::NewObject("({ val : 123 })");
712   // Test IC miss.
713   Handle<Object> result;
714   callable(object).ToHandleChecked();
715   CHECK(Runtime::GetObjectProperty(isolate, object, name).ToHandle(&result));
716   CHECK_EQ(Smi::cast(*result), Smi::FromInt(999));
717 
718   // Test transition to monomorphic IC.
719   callable(object).ToHandleChecked();
720   CHECK(Runtime::GetObjectProperty(isolate, object, name).ToHandle(&result));
721   CHECK_EQ(Smi::cast(*result), Smi::FromInt(999));
722 
723   // Test transition to polymorphic IC.
724   Handle<Object> object2 =
725       InterpreterTester::NewObject("({ val : 456, other : 123 })");
726   callable(object2).ToHandleChecked();
727   CHECK(Runtime::GetObjectProperty(isolate, object2, name).ToHandle(&result));
728   CHECK_EQ(Smi::cast(*result), Smi::FromInt(999));
729 
730   // Test transition to megamorphic IC.
731   Handle<Object> object3 =
732       InterpreterTester::NewObject("({ val : 789, val2 : 123 })");
733   callable(object3).ToHandleChecked();
734   Handle<Object> object4 =
735       InterpreterTester::NewObject("({ val : 789, val3 : 123 })");
736   callable(object4).ToHandleChecked();
737   Handle<Object> object5 =
738       InterpreterTester::NewObject("({ val : 789, val4 : 123 })");
739   callable(object5).ToHandleChecked();
740   CHECK(Runtime::GetObjectProperty(isolate, object5, name).ToHandle(&result));
741   CHECK_EQ(Smi::cast(*result), Smi::FromInt(999));
742 }
743 
744 
TEST(InterpreterStoreKeyedProperty)745 TEST(InterpreterStoreKeyedProperty) {
746   HandleAndZoneScope handles;
747   i::Isolate* isolate = handles.main_isolate();
748   i::Factory* factory = isolate->factory();
749   i::Zone zone(isolate->allocator());
750 
751   i::FeedbackVectorSpec feedback_spec(&zone);
752   i::FeedbackVectorSlot slot = feedback_spec.AddKeyedStoreICSlot();
753 
754   Handle<i::TypeFeedbackVector> vector =
755       i::NewTypeFeedbackVector(isolate, &feedback_spec);
756 
757   Handle<i::String> name = factory->NewStringFromAsciiChecked("val");
758   name = factory->string_table()->LookupString(isolate, name);
759 
760   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
761                                0, 1);
762 
763   builder.LoadLiteral(name)
764       .StoreAccumulatorInRegister(Register(0))
765       .LoadLiteral(Smi::FromInt(999))
766       .StoreKeyedProperty(builder.Parameter(0), Register(0),
767                           vector->GetIndex(slot), i::SLOPPY)
768       .Return();
769   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
770 
771   InterpreterTester tester(isolate, bytecode_array, vector);
772   auto callable = tester.GetCallable<Handle<Object>>();
773   Handle<Object> object = InterpreterTester::NewObject("({ val : 123 })");
774   // Test IC miss.
775   Handle<Object> result;
776   callable(object).ToHandleChecked();
777   CHECK(Runtime::GetObjectProperty(isolate, object, name).ToHandle(&result));
778   CHECK_EQ(Smi::cast(*result), Smi::FromInt(999));
779 
780   // Test transition to monomorphic IC.
781   callable(object).ToHandleChecked();
782   CHECK(Runtime::GetObjectProperty(isolate, object, name).ToHandle(&result));
783   CHECK_EQ(Smi::cast(*result), Smi::FromInt(999));
784 
785   // Test transition to megamorphic IC.
786   Handle<Object> object2 =
787       InterpreterTester::NewObject("({ val : 456, other : 123 })");
788   callable(object2).ToHandleChecked();
789   CHECK(Runtime::GetObjectProperty(isolate, object2, name).ToHandle(&result));
790   CHECK_EQ(Smi::cast(*result), Smi::FromInt(999));
791 }
792 
TestInterpreterCall(TailCallMode tail_call_mode)793 static void TestInterpreterCall(TailCallMode tail_call_mode) {
794   HandleAndZoneScope handles;
795   i::Isolate* isolate = handles.main_isolate();
796   i::Factory* factory = isolate->factory();
797   i::Zone zone(isolate->allocator());
798 
799   i::FeedbackVectorSpec feedback_spec(&zone);
800   i::FeedbackVectorSlot slot = feedback_spec.AddLoadICSlot();
801 
802   Handle<i::TypeFeedbackVector> vector =
803       i::NewTypeFeedbackVector(isolate, &feedback_spec);
804   int slot_index = vector->GetIndex(slot);
805 
806   Handle<i::String> name = factory->NewStringFromAsciiChecked("func");
807   name = factory->string_table()->LookupString(isolate, name);
808 
809   // Check with no args.
810   {
811     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
812                                  0, 1);
813 
814     builder.LoadNamedProperty(builder.Parameter(0), name, slot_index)
815         .StoreAccumulatorInRegister(Register(0))
816         .Call(Register(0), builder.Parameter(0), 1, 0, tail_call_mode)
817         .Return();
818     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
819 
820     InterpreterTester tester(handles.main_isolate(), bytecode_array, vector);
821     auto callable = tester.GetCallable<Handle<Object>>();
822 
823     Handle<Object> object = InterpreterTester::NewObject(
824         "new (function Obj() { this.func = function() { return 0x265; }})()");
825     Handle<Object> return_val = callable(object).ToHandleChecked();
826     CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(0x265));
827   }
828 
829   // Check that receiver is passed properly.
830   {
831     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
832                                  0, 1);
833 
834     builder.LoadNamedProperty(builder.Parameter(0), name, slot_index)
835         .StoreAccumulatorInRegister(Register(0))
836         .Call(Register(0), builder.Parameter(0), 1, 0, tail_call_mode)
837         .Return();
838     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
839 
840     InterpreterTester tester(handles.main_isolate(), bytecode_array, vector);
841     auto callable = tester.GetCallable<Handle<Object>>();
842 
843     Handle<Object> object = InterpreterTester::NewObject(
844         "new (function Obj() {"
845         "  this.val = 1234;"
846         "  this.func = function() { return this.val; };"
847         "})()");
848     Handle<Object> return_val = callable(object).ToHandleChecked();
849     CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(1234));
850   }
851 
852   // Check with two parameters (+ receiver).
853   {
854     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
855                                  0, 4);
856 
857     builder.LoadNamedProperty(builder.Parameter(0), name, slot_index)
858         .StoreAccumulatorInRegister(Register(0))
859         .LoadAccumulatorWithRegister(builder.Parameter(0))
860         .StoreAccumulatorInRegister(Register(1))
861         .LoadLiteral(Smi::FromInt(51))
862         .StoreAccumulatorInRegister(Register(2))
863         .LoadLiteral(Smi::FromInt(11))
864         .StoreAccumulatorInRegister(Register(3))
865         .Call(Register(0), Register(1), 3, 0, tail_call_mode)
866         .Return();
867     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
868 
869     InterpreterTester tester(handles.main_isolate(), bytecode_array, vector);
870     auto callable = tester.GetCallable<Handle<Object>>();
871 
872     Handle<Object> object = InterpreterTester::NewObject(
873         "new (function Obj() { "
874         "  this.func = function(a, b) { return a - b; }"
875         "})()");
876     Handle<Object> return_val = callable(object).ToHandleChecked();
877     CHECK(return_val->SameValue(Smi::FromInt(40)));
878   }
879 
880   // Check with 10 parameters (+ receiver).
881   {
882     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
883                                  0, 12);
884 
885     builder.LoadNamedProperty(builder.Parameter(0), name, slot_index)
886         .StoreAccumulatorInRegister(Register(0))
887         .LoadAccumulatorWithRegister(builder.Parameter(0))
888         .StoreAccumulatorInRegister(Register(1))
889         .LoadLiteral(factory->NewStringFromAsciiChecked("a"))
890         .StoreAccumulatorInRegister(Register(2))
891         .LoadLiteral(factory->NewStringFromAsciiChecked("b"))
892         .StoreAccumulatorInRegister(Register(3))
893         .LoadLiteral(factory->NewStringFromAsciiChecked("c"))
894         .StoreAccumulatorInRegister(Register(4))
895         .LoadLiteral(factory->NewStringFromAsciiChecked("d"))
896         .StoreAccumulatorInRegister(Register(5))
897         .LoadLiteral(factory->NewStringFromAsciiChecked("e"))
898         .StoreAccumulatorInRegister(Register(6))
899         .LoadLiteral(factory->NewStringFromAsciiChecked("f"))
900         .StoreAccumulatorInRegister(Register(7))
901         .LoadLiteral(factory->NewStringFromAsciiChecked("g"))
902         .StoreAccumulatorInRegister(Register(8))
903         .LoadLiteral(factory->NewStringFromAsciiChecked("h"))
904         .StoreAccumulatorInRegister(Register(9))
905         .LoadLiteral(factory->NewStringFromAsciiChecked("i"))
906         .StoreAccumulatorInRegister(Register(10))
907         .LoadLiteral(factory->NewStringFromAsciiChecked("j"))
908         .StoreAccumulatorInRegister(Register(11))
909         .Call(Register(0), Register(1), 11, 0, tail_call_mode)
910         .Return();
911     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
912 
913     InterpreterTester tester(handles.main_isolate(), bytecode_array, vector);
914     auto callable = tester.GetCallable<Handle<Object>>();
915 
916     Handle<Object> object = InterpreterTester::NewObject(
917         "new (function Obj() { "
918         "  this.prefix = \"prefix_\";"
919         "  this.func = function(a, b, c, d, e, f, g, h, i, j) {"
920         "      return this.prefix + a + b + c + d + e + f + g + h + i + j;"
921         "  }"
922         "})()");
923     Handle<Object> return_val = callable(object).ToHandleChecked();
924     Handle<i::String> expected =
925         factory->NewStringFromAsciiChecked("prefix_abcdefghij");
926     CHECK(i::String::cast(*return_val)->Equals(*expected));
927   }
928 }
929 
TEST(InterpreterCall)930 TEST(InterpreterCall) { TestInterpreterCall(TailCallMode::kDisallow); }
931 
TEST(InterpreterTailCall)932 TEST(InterpreterTailCall) { TestInterpreterCall(TailCallMode::kAllow); }
933 
SetRegister(BytecodeArrayBuilder & builder,Register reg,int value,Register scratch)934 static BytecodeArrayBuilder& SetRegister(BytecodeArrayBuilder& builder,
935                                          Register reg, int value,
936                                          Register scratch) {
937   return builder.StoreAccumulatorInRegister(scratch)
938       .LoadLiteral(Smi::FromInt(value))
939       .StoreAccumulatorInRegister(reg)
940       .LoadAccumulatorWithRegister(scratch);
941 }
942 
943 
IncrementRegister(BytecodeArrayBuilder & builder,Register reg,int value,Register scratch)944 static BytecodeArrayBuilder& IncrementRegister(BytecodeArrayBuilder& builder,
945                                                Register reg, int value,
946                                                Register scratch) {
947   return builder.StoreAccumulatorInRegister(scratch)
948       .LoadLiteral(Smi::FromInt(value))
949       .BinaryOperation(Token::Value::ADD, reg)
950       .StoreAccumulatorInRegister(reg)
951       .LoadAccumulatorWithRegister(scratch);
952 }
953 
954 
TEST(InterpreterJumps)955 TEST(InterpreterJumps) {
956   HandleAndZoneScope handles;
957   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
958                                0, 2);
959 
960   Register reg(0), scratch(1);
961   BytecodeLabel label[3];
962 
963   builder.LoadLiteral(Smi::FromInt(0))
964       .StoreAccumulatorInRegister(reg)
965       .Jump(&label[1]);
966   SetRegister(builder, reg, 1024, scratch).Bind(&label[0]);
967   IncrementRegister(builder, reg, 1, scratch).Jump(&label[2]);
968   SetRegister(builder, reg, 2048, scratch).Bind(&label[1]);
969   IncrementRegister(builder, reg, 2, scratch).Jump(&label[0]);
970   SetRegister(builder, reg, 4096, scratch).Bind(&label[2]);
971   IncrementRegister(builder, reg, 4, scratch)
972       .LoadAccumulatorWithRegister(reg)
973       .Return();
974 
975   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
976   InterpreterTester tester(handles.main_isolate(), bytecode_array);
977   auto callable = tester.GetCallable<>();
978   Handle<Object> return_value = callable().ToHandleChecked();
979   CHECK_EQ(Smi::cast(*return_value)->value(), 7);
980 }
981 
982 
TEST(InterpreterConditionalJumps)983 TEST(InterpreterConditionalJumps) {
984   HandleAndZoneScope handles;
985   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
986                                0, 2);
987 
988   Register reg(0), scratch(1);
989   BytecodeLabel label[2];
990   BytecodeLabel done, done1;
991 
992   builder.LoadLiteral(Smi::FromInt(0))
993       .StoreAccumulatorInRegister(reg)
994       .LoadFalse()
995       .JumpIfFalse(&label[0]);
996   IncrementRegister(builder, reg, 1024, scratch)
997       .Bind(&label[0])
998       .LoadTrue()
999       .JumpIfFalse(&done);
1000   IncrementRegister(builder, reg, 1, scratch).LoadTrue().JumpIfTrue(&label[1]);
1001   IncrementRegister(builder, reg, 2048, scratch).Bind(&label[1]);
1002   IncrementRegister(builder, reg, 2, scratch).LoadFalse().JumpIfTrue(&done1);
1003   IncrementRegister(builder, reg, 4, scratch)
1004       .LoadAccumulatorWithRegister(reg)
1005       .Bind(&done)
1006       .Bind(&done1)
1007       .Return();
1008 
1009   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
1010   InterpreterTester tester(handles.main_isolate(), bytecode_array);
1011   auto callable = tester.GetCallable<>();
1012   Handle<Object> return_value = callable().ToHandleChecked();
1013   CHECK_EQ(Smi::cast(*return_value)->value(), 7);
1014 }
1015 
TEST(InterpreterConditionalJumps2)1016 TEST(InterpreterConditionalJumps2) {
1017   // TODO(oth): Add tests for all conditional jumps near and far.
1018   HandleAndZoneScope handles;
1019   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
1020                                0, 2);
1021 
1022   Register reg(0), scratch(1);
1023   BytecodeLabel label[2];
1024   BytecodeLabel done, done1;
1025 
1026   builder.LoadLiteral(Smi::FromInt(0))
1027       .StoreAccumulatorInRegister(reg)
1028       .LoadFalse()
1029       .JumpIfFalse(&label[0]);
1030   IncrementRegister(builder, reg, 1024, scratch)
1031       .Bind(&label[0])
1032       .LoadTrue()
1033       .JumpIfFalse(&done);
1034   IncrementRegister(builder, reg, 1, scratch).LoadTrue().JumpIfTrue(&label[1]);
1035   IncrementRegister(builder, reg, 2048, scratch).Bind(&label[1]);
1036   IncrementRegister(builder, reg, 2, scratch).LoadFalse().JumpIfTrue(&done1);
1037   IncrementRegister(builder, reg, 4, scratch)
1038       .LoadAccumulatorWithRegister(reg)
1039       .Bind(&done)
1040       .Bind(&done1)
1041       .Return();
1042 
1043   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
1044   InterpreterTester tester(handles.main_isolate(), bytecode_array);
1045   auto callable = tester.GetCallable<>();
1046   Handle<Object> return_value = callable().ToHandleChecked();
1047   CHECK_EQ(Smi::cast(*return_value)->value(), 7);
1048 }
1049 
TEST(InterpreterJumpConstantWith16BitOperand)1050 TEST(InterpreterJumpConstantWith16BitOperand) {
1051   HandleAndZoneScope handles;
1052   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
1053                                0, 257);
1054 
1055   Register reg(0), scratch(256);
1056   BytecodeLabel done, fake;
1057 
1058   builder.LoadLiteral(Smi::FromInt(0));
1059   builder.StoreAccumulatorInRegister(reg);
1060   // Consume all 8-bit operands
1061   for (int i = 1; i <= 256; i++) {
1062     builder.LoadLiteral(handles.main_isolate()->factory()->NewNumber(i));
1063     builder.BinaryOperation(Token::Value::ADD, reg);
1064     builder.StoreAccumulatorInRegister(reg);
1065   }
1066   builder.Jump(&done);
1067 
1068   // Emit more than 16-bit immediate operands worth of code to jump over.
1069   builder.Bind(&fake);
1070   for (int i = 0; i < 6600; i++) {
1071     builder.LoadLiteral(Smi::FromInt(0));                 // 1-byte
1072     builder.BinaryOperation(Token::Value::ADD, scratch);  // 4-bytes
1073     builder.StoreAccumulatorInRegister(scratch);          // 4-bytes
1074     builder.MoveRegister(scratch, reg);                   // 6-bytes
1075   }
1076   builder.Bind(&done);
1077   builder.LoadAccumulatorWithRegister(reg);
1078   builder.Return();
1079 
1080   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
1081   BytecodeArrayIterator iterator(bytecode_array);
1082 
1083   bool found_16bit_constant_jump = false;
1084   while (!iterator.done()) {
1085     if (iterator.current_bytecode() == Bytecode::kJumpConstant &&
1086         iterator.current_operand_scale() == OperandScale::kDouble) {
1087       found_16bit_constant_jump = true;
1088       break;
1089     }
1090     iterator.Advance();
1091   }
1092   CHECK(found_16bit_constant_jump);
1093 
1094   InterpreterTester tester(handles.main_isolate(), bytecode_array);
1095   auto callable = tester.GetCallable<>();
1096   Handle<Object> return_value = callable().ToHandleChecked();
1097   CHECK_EQ(Smi::cast(*return_value)->value(), 256.0 / 2 * (1 + 256));
1098 }
1099 
TEST(InterpreterJumpWith32BitOperand)1100 TEST(InterpreterJumpWith32BitOperand) {
1101   HandleAndZoneScope handles;
1102   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
1103                                0, 1);
1104   Register reg(0);
1105   BytecodeLabel done;
1106 
1107   builder.LoadLiteral(Smi::FromInt(0));
1108   builder.StoreAccumulatorInRegister(reg);
1109   // Consume all 16-bit constant pool entries
1110   for (int i = 1; i <= 65536; i++) {
1111     builder.LoadLiteral(handles.main_isolate()->factory()->NewNumber(i));
1112   }
1113   builder.Jump(&done);
1114   builder.LoadLiteral(Smi::FromInt(0));
1115   builder.Bind(&done);
1116   builder.Return();
1117 
1118   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
1119   BytecodeArrayIterator iterator(bytecode_array);
1120 
1121   bool found_32bit_jump = false;
1122   while (!iterator.done()) {
1123     if (iterator.current_bytecode() == Bytecode::kJump &&
1124         iterator.current_operand_scale() == OperandScale::kQuadruple) {
1125       found_32bit_jump = true;
1126       break;
1127     }
1128     iterator.Advance();
1129   }
1130   CHECK(found_32bit_jump);
1131 
1132   InterpreterTester tester(handles.main_isolate(), bytecode_array);
1133   auto callable = tester.GetCallable<>();
1134   Handle<Object> return_value = callable().ToHandleChecked();
1135   CHECK_EQ(Smi::cast(*return_value)->value(), 65536.0);
1136 }
1137 
1138 static const Token::Value kComparisonTypes[] = {
1139     Token::Value::EQ, Token::Value::NE,  Token::Value::EQ_STRICT,
1140     Token::Value::LT, Token::Value::LTE, Token::Value::GT,
1141     Token::Value::GTE};
1142 
1143 template <typename T>
CompareC(Token::Value op,T lhs,T rhs,bool types_differed=false)1144 bool CompareC(Token::Value op, T lhs, T rhs, bool types_differed = false) {
1145   switch (op) {
1146     case Token::Value::EQ:
1147       return lhs == rhs;
1148     case Token::Value::NE:
1149       return lhs != rhs;
1150     case Token::Value::EQ_STRICT:
1151       return (lhs == rhs) && !types_differed;
1152     case Token::Value::NE_STRICT:
1153       return (lhs != rhs) || types_differed;
1154     case Token::Value::LT:
1155       return lhs < rhs;
1156     case Token::Value::LTE:
1157       return lhs <= rhs;
1158     case Token::Value::GT:
1159       return lhs > rhs;
1160     case Token::Value::GTE:
1161       return lhs >= rhs;
1162     default:
1163       UNREACHABLE();
1164       return false;
1165   }
1166 }
1167 
1168 
TEST(InterpreterSmiComparisons)1169 TEST(InterpreterSmiComparisons) {
1170   // NB Constants cover 31-bit space.
1171   int inputs[] = {v8::internal::kMinInt / 2,
1172                   v8::internal::kMinInt / 4,
1173                   -108733832,
1174                   -999,
1175                   -42,
1176                   -2,
1177                   -1,
1178                   0,
1179                   +1,
1180                   +2,
1181                   42,
1182                   12345678,
1183                   v8::internal::kMaxInt / 4,
1184                   v8::internal::kMaxInt / 2};
1185 
1186   for (size_t c = 0; c < arraysize(kComparisonTypes); c++) {
1187     Token::Value comparison = kComparisonTypes[c];
1188     for (size_t i = 0; i < arraysize(inputs); i++) {
1189       for (size_t j = 0; j < arraysize(inputs); j++) {
1190         HandleAndZoneScope handles;
1191         BytecodeArrayBuilder builder(handles.main_isolate(),
1192                                      handles.main_zone(), 0, 0, 1);
1193 
1194         Register r0(0);
1195         builder.LoadLiteral(Smi::FromInt(inputs[i]))
1196             .StoreAccumulatorInRegister(r0)
1197             .LoadLiteral(Smi::FromInt(inputs[j]))
1198             .CompareOperation(comparison, r0)
1199             .Return();
1200 
1201         Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
1202         InterpreterTester tester(handles.main_isolate(), bytecode_array);
1203         auto callable = tester.GetCallable<>();
1204         Handle<Object> return_value = callable().ToHandleChecked();
1205         CHECK(return_value->IsBoolean());
1206         CHECK_EQ(return_value->BooleanValue(),
1207                  CompareC(comparison, inputs[i], inputs[j]));
1208       }
1209     }
1210   }
1211 }
1212 
1213 
TEST(InterpreterHeapNumberComparisons)1214 TEST(InterpreterHeapNumberComparisons) {
1215   double inputs[] = {std::numeric_limits<double>::min(),
1216                      std::numeric_limits<double>::max(),
1217                      -0.001,
1218                      0.01,
1219                      0.1000001,
1220                      1e99,
1221                      -1e-99};
1222   for (size_t c = 0; c < arraysize(kComparisonTypes); c++) {
1223     Token::Value comparison = kComparisonTypes[c];
1224     for (size_t i = 0; i < arraysize(inputs); i++) {
1225       for (size_t j = 0; j < arraysize(inputs); j++) {
1226         HandleAndZoneScope handles;
1227         i::Factory* factory = handles.main_isolate()->factory();
1228         BytecodeArrayBuilder builder(handles.main_isolate(),
1229                                      handles.main_zone(), 0, 0, 1);
1230 
1231         Register r0(0);
1232         builder.LoadLiteral(factory->NewHeapNumber(inputs[i]))
1233             .StoreAccumulatorInRegister(r0)
1234             .LoadLiteral(factory->NewHeapNumber(inputs[j]))
1235             .CompareOperation(comparison, r0)
1236             .Return();
1237 
1238         Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
1239         InterpreterTester tester(handles.main_isolate(), bytecode_array);
1240         auto callable = tester.GetCallable<>();
1241         Handle<Object> return_value = callable().ToHandleChecked();
1242         CHECK(return_value->IsBoolean());
1243         CHECK_EQ(return_value->BooleanValue(),
1244                  CompareC(comparison, inputs[i], inputs[j]));
1245       }
1246     }
1247   }
1248 }
1249 
1250 
TEST(InterpreterStringComparisons)1251 TEST(InterpreterStringComparisons) {
1252   std::string inputs[] = {"A", "abc", "z", "", "Foo!", "Foo"};
1253 
1254   for (size_t c = 0; c < arraysize(kComparisonTypes); c++) {
1255     Token::Value comparison = kComparisonTypes[c];
1256     for (size_t i = 0; i < arraysize(inputs); i++) {
1257       for (size_t j = 0; j < arraysize(inputs); j++) {
1258         const char* lhs = inputs[i].c_str();
1259         const char* rhs = inputs[j].c_str();
1260         HandleAndZoneScope handles;
1261         i::Factory* factory = handles.main_isolate()->factory();
1262         BytecodeArrayBuilder builder(handles.main_isolate(),
1263                                      handles.main_zone(), 0, 0, 1);
1264 
1265         Register r0(0);
1266         builder.LoadLiteral(factory->NewStringFromAsciiChecked(lhs))
1267             .StoreAccumulatorInRegister(r0)
1268             .LoadLiteral(factory->NewStringFromAsciiChecked(rhs))
1269             .CompareOperation(comparison, r0)
1270             .Return();
1271 
1272         Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
1273         InterpreterTester tester(handles.main_isolate(), bytecode_array);
1274         auto callable = tester.GetCallable<>();
1275         Handle<Object> return_value = callable().ToHandleChecked();
1276         CHECK(return_value->IsBoolean());
1277         CHECK_EQ(return_value->BooleanValue(),
1278                  CompareC(comparison, inputs[i], inputs[j]));
1279       }
1280     }
1281   }
1282 }
1283 
1284 
TEST(InterpreterMixedComparisons)1285 TEST(InterpreterMixedComparisons) {
1286   // This test compares a HeapNumber with a String. The latter is
1287   // convertible to a HeapNumber so comparison will be between numeric
1288   // values except for the strict comparisons where no conversion is
1289   // performed.
1290   const char* inputs[] = {"-1.77", "-40.333", "0.01", "55.77e5", "2.01"};
1291 
1292   i::UnicodeCache unicode_cache;
1293 
1294   for (size_t c = 0; c < arraysize(kComparisonTypes); c++) {
1295     Token::Value comparison = kComparisonTypes[c];
1296     for (size_t i = 0; i < arraysize(inputs); i++) {
1297       for (size_t j = 0; j < arraysize(inputs); j++) {
1298         for (int pass = 0; pass < 2; pass++) {
1299           const char* lhs_cstr = inputs[i];
1300           const char* rhs_cstr = inputs[j];
1301           double lhs = StringToDouble(&unicode_cache, lhs_cstr,
1302                                       i::ConversionFlags::NO_FLAGS);
1303           double rhs = StringToDouble(&unicode_cache, rhs_cstr,
1304                                       i::ConversionFlags::NO_FLAGS);
1305           HandleAndZoneScope handles;
1306           i::Factory* factory = handles.main_isolate()->factory();
1307           BytecodeArrayBuilder builder(handles.main_isolate(),
1308                                        handles.main_zone(), 0, 0, 1);
1309 
1310           Register r0(0);
1311           if (pass == 0) {
1312             // Comparison with HeapNumber on the lhs and String on the rhs
1313             builder.LoadLiteral(factory->NewNumber(lhs))
1314                 .StoreAccumulatorInRegister(r0)
1315                 .LoadLiteral(factory->NewStringFromAsciiChecked(rhs_cstr))
1316                 .CompareOperation(comparison, r0)
1317                 .Return();
1318           } else {
1319             // Comparison with HeapNumber on the rhs and String on the lhs
1320             builder.LoadLiteral(factory->NewStringFromAsciiChecked(lhs_cstr))
1321                 .StoreAccumulatorInRegister(r0)
1322                 .LoadLiteral(factory->NewNumber(rhs))
1323                 .CompareOperation(comparison, r0)
1324                 .Return();
1325           }
1326 
1327           Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
1328           InterpreterTester tester(handles.main_isolate(), bytecode_array);
1329           auto callable = tester.GetCallable<>();
1330           Handle<Object> return_value = callable().ToHandleChecked();
1331           CHECK(return_value->IsBoolean());
1332           CHECK_EQ(return_value->BooleanValue(),
1333                    CompareC(comparison, lhs, rhs, true));
1334         }
1335       }
1336     }
1337   }
1338 }
1339 
TEST(InterpreterStrictNotEqual)1340 TEST(InterpreterStrictNotEqual) {
1341   HandleAndZoneScope handles;
1342   i::Factory* factory = handles.main_isolate()->factory();
1343   const char* code_snippet =
1344       "function f(lhs, rhs) {\n"
1345       "  return lhs !== rhs;\n"
1346       "}\n"
1347       "f(0, 0);\n";
1348   InterpreterTester tester(handles.main_isolate(), code_snippet);
1349   auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
1350 
1351   // Test passing different types.
1352   const char* inputs[] = {"-1.77", "-40.333", "0.01", "55.77e5", "2.01"};
1353   i::UnicodeCache unicode_cache;
1354   for (size_t i = 0; i < arraysize(inputs); i++) {
1355     for (size_t j = 0; j < arraysize(inputs); j++) {
1356       double lhs = StringToDouble(&unicode_cache, inputs[i],
1357                                   i::ConversionFlags::NO_FLAGS);
1358       double rhs = StringToDouble(&unicode_cache, inputs[j],
1359                                   i::ConversionFlags::NO_FLAGS);
1360       Handle<Object> lhs_obj = factory->NewNumber(lhs);
1361       Handle<Object> rhs_obj = factory->NewStringFromAsciiChecked(inputs[j]);
1362 
1363       Handle<Object> return_value =
1364           callable(lhs_obj, rhs_obj).ToHandleChecked();
1365       CHECK(return_value->IsBoolean());
1366       CHECK_EQ(return_value->BooleanValue(),
1367                CompareC(Token::Value::NE_STRICT, lhs, rhs, true));
1368     }
1369   }
1370 
1371   // Test passing string types.
1372   const char* inputs_str[] = {"A", "abc", "z", "", "Foo!", "Foo"};
1373   for (size_t i = 0; i < arraysize(inputs_str); i++) {
1374     for (size_t j = 0; j < arraysize(inputs_str); j++) {
1375       Handle<Object> lhs_obj =
1376           factory->NewStringFromAsciiChecked(inputs_str[i]);
1377       Handle<Object> rhs_obj =
1378           factory->NewStringFromAsciiChecked(inputs_str[j]);
1379 
1380       Handle<Object> return_value =
1381           callable(lhs_obj, rhs_obj).ToHandleChecked();
1382       CHECK(return_value->IsBoolean());
1383       CHECK_EQ(return_value->BooleanValue(),
1384                CompareC(Token::Value::NE_STRICT, inputs_str[i], inputs_str[j]));
1385     }
1386   }
1387 
1388   // Test passing doubles.
1389   double inputs_number[] = {std::numeric_limits<double>::min(),
1390                             std::numeric_limits<double>::max(),
1391                             -0.001,
1392                             0.01,
1393                             0.1000001,
1394                             1e99,
1395                             -1e-99};
1396   for (size_t i = 0; i < arraysize(inputs_number); i++) {
1397     for (size_t j = 0; j < arraysize(inputs_number); j++) {
1398       Handle<Object> lhs_obj = factory->NewNumber(inputs_number[i]);
1399       Handle<Object> rhs_obj = factory->NewNumber(inputs_number[j]);
1400 
1401       Handle<Object> return_value =
1402           callable(lhs_obj, rhs_obj).ToHandleChecked();
1403       CHECK(return_value->IsBoolean());
1404       CHECK_EQ(return_value->BooleanValue(),
1405                CompareC(Token::Value::NE_STRICT, inputs_number[i],
1406                         inputs_number[j]));
1407     }
1408   }
1409 }
1410 
TEST(InterpreterInstanceOf)1411 TEST(InterpreterInstanceOf) {
1412   HandleAndZoneScope handles;
1413   i::Factory* factory = handles.main_isolate()->factory();
1414   Handle<i::String> name = factory->NewStringFromAsciiChecked("cons");
1415   Handle<i::JSFunction> func = factory->NewFunction(name);
1416   Handle<i::JSObject> instance = factory->NewJSObject(func);
1417   Handle<i::Object> other = factory->NewNumber(3.3333);
1418   Handle<i::Object> cases[] = {Handle<i::Object>::cast(instance), other};
1419   for (size_t i = 0; i < arraysize(cases); i++) {
1420     bool expected_value = (i == 0);
1421     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
1422                                  0, 1);
1423 
1424     Register r0(0);
1425     builder.LoadLiteral(cases[i]);
1426     builder.StoreAccumulatorInRegister(r0)
1427         .LoadLiteral(func)
1428         .CompareOperation(Token::Value::INSTANCEOF, r0)
1429         .Return();
1430 
1431     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
1432     InterpreterTester tester(handles.main_isolate(), bytecode_array);
1433     auto callable = tester.GetCallable<>();
1434     Handle<Object> return_value = callable().ToHandleChecked();
1435     CHECK(return_value->IsBoolean());
1436     CHECK_EQ(return_value->BooleanValue(), expected_value);
1437   }
1438 }
1439 
1440 
TEST(InterpreterTestIn)1441 TEST(InterpreterTestIn) {
1442   HandleAndZoneScope handles;
1443   i::Factory* factory = handles.main_isolate()->factory();
1444   // Allocate an array
1445   Handle<i::JSArray> array =
1446       factory->NewJSArray(0, i::ElementsKind::FAST_SMI_ELEMENTS);
1447   // Check for these properties on the array object
1448   const char* properties[] = {"length", "fuzzle", "x", "0"};
1449   for (size_t i = 0; i < arraysize(properties); i++) {
1450     bool expected_value = (i == 0);
1451     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
1452                                  0, 1);
1453 
1454     Register r0(0);
1455     builder.LoadLiteral(factory->NewStringFromAsciiChecked(properties[i]))
1456         .StoreAccumulatorInRegister(r0)
1457         .LoadLiteral(Handle<Object>::cast(array))
1458         .CompareOperation(Token::Value::IN, r0)
1459         .Return();
1460 
1461     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
1462     InterpreterTester tester(handles.main_isolate(), bytecode_array);
1463     auto callable = tester.GetCallable<>();
1464     Handle<Object> return_value = callable().ToHandleChecked();
1465     CHECK(return_value->IsBoolean());
1466     CHECK_EQ(return_value->BooleanValue(), expected_value);
1467   }
1468 }
1469 
1470 
TEST(InterpreterUnaryNot)1471 TEST(InterpreterUnaryNot) {
1472   HandleAndZoneScope handles;
1473   for (size_t i = 1; i < 10; i++) {
1474     bool expected_value = ((i & 1) == 1);
1475     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
1476                                  0, 0);
1477 
1478     Register r0(0);
1479     builder.LoadFalse();
1480     for (size_t j = 0; j < i; j++) {
1481       builder.LogicalNot();
1482     }
1483     builder.Return();
1484     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
1485     InterpreterTester tester(handles.main_isolate(), bytecode_array);
1486     auto callable = tester.GetCallable<>();
1487     Handle<Object> return_value = callable().ToHandleChecked();
1488     CHECK(return_value->IsBoolean());
1489     CHECK_EQ(return_value->BooleanValue(), expected_value);
1490   }
1491 }
1492 
1493 
LoadAny(BytecodeArrayBuilder * builder,v8::internal::Factory * factory,Handle<Object> obj)1494 static void LoadAny(BytecodeArrayBuilder* builder,
1495                     v8::internal::Factory* factory, Handle<Object> obj) {
1496   if (obj->IsOddball()) {
1497     if (obj->SameValue(*factory->true_value())) {
1498       builder->LoadTrue();
1499     } else if (obj->SameValue(*factory->false_value())) {
1500       builder->LoadFalse();
1501     } else if (obj->SameValue(*factory->the_hole_value())) {
1502       builder->LoadTheHole();
1503     } else if (obj->SameValue(*factory->null_value())) {
1504       builder->LoadNull();
1505     } else if (obj->SameValue(*factory->undefined_value())) {
1506       builder->LoadUndefined();
1507     } else {
1508       UNREACHABLE();
1509     }
1510   } else if (obj->IsSmi()) {
1511     builder->LoadLiteral(*Handle<Smi>::cast(obj));
1512   } else {
1513     builder->LoadLiteral(obj);
1514   }
1515 }
1516 
1517 
TEST(InterpreterUnaryNotNonBoolean)1518 TEST(InterpreterUnaryNotNonBoolean) {
1519   HandleAndZoneScope handles;
1520   i::Factory* factory = handles.main_isolate()->factory();
1521 
1522   std::pair<Handle<Object>, bool> object_type_tuples[] = {
1523       std::make_pair(factory->undefined_value(), true),
1524       std::make_pair(factory->null_value(), true),
1525       std::make_pair(factory->false_value(), true),
1526       std::make_pair(factory->true_value(), false),
1527       std::make_pair(factory->NewNumber(9.1), false),
1528       std::make_pair(factory->NewNumberFromInt(0), true),
1529       std::make_pair(
1530           Handle<Object>::cast(factory->NewStringFromStaticChars("hello")),
1531           false),
1532       std::make_pair(
1533           Handle<Object>::cast(factory->NewStringFromStaticChars("")), true),
1534   };
1535 
1536   for (size_t i = 0; i < arraysize(object_type_tuples); i++) {
1537     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
1538                                  0, 0);
1539 
1540     Register r0(0);
1541     LoadAny(&builder, factory, object_type_tuples[i].first);
1542     builder.LogicalNot();
1543     builder.Return();
1544     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
1545     InterpreterTester tester(handles.main_isolate(), bytecode_array);
1546     auto callable = tester.GetCallable<>();
1547     Handle<Object> return_value = callable().ToHandleChecked();
1548     CHECK(return_value->IsBoolean());
1549     CHECK_EQ(return_value->BooleanValue(), object_type_tuples[i].second);
1550   }
1551 }
1552 
1553 
TEST(InterpreterTypeof)1554 TEST(InterpreterTypeof) {
1555   HandleAndZoneScope handles;
1556 
1557   std::pair<const char*, const char*> typeof_vals[] = {
1558       std::make_pair("return typeof undefined;", "undefined"),
1559       std::make_pair("return typeof null;", "object"),
1560       std::make_pair("return typeof true;", "boolean"),
1561       std::make_pair("return typeof false;", "boolean"),
1562       std::make_pair("return typeof 9.1;", "number"),
1563       std::make_pair("return typeof 7771;", "number"),
1564       std::make_pair("return typeof 'hello';", "string"),
1565       std::make_pair("return typeof global_unallocated;", "undefined"),
1566   };
1567 
1568   for (size_t i = 0; i < arraysize(typeof_vals); i++) {
1569     std::string source(InterpreterTester::SourceForBody(typeof_vals[i].first));
1570     InterpreterTester tester(handles.main_isolate(), source.c_str());
1571 
1572     auto callable = tester.GetCallable<>();
1573     Handle<v8::internal::String> return_value =
1574         Handle<v8::internal::String>::cast(callable().ToHandleChecked());
1575     auto actual = return_value->ToCString();
1576     CHECK_EQ(strcmp(&actual[0], typeof_vals[i].second), 0);
1577   }
1578 }
1579 
1580 
TEST(InterpreterCallRuntime)1581 TEST(InterpreterCallRuntime) {
1582   HandleAndZoneScope handles;
1583 
1584   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
1585                                0, 2);
1586 
1587   builder.LoadLiteral(Smi::FromInt(15))
1588       .StoreAccumulatorInRegister(Register(0))
1589       .LoadLiteral(Smi::FromInt(40))
1590       .StoreAccumulatorInRegister(Register(1))
1591       .CallRuntime(Runtime::kAdd, Register(0), 2)
1592       .Return();
1593   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
1594 
1595   InterpreterTester tester(handles.main_isolate(), bytecode_array);
1596   auto callable = tester.GetCallable<>();
1597 
1598   Handle<Object> return_val = callable().ToHandleChecked();
1599   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(55));
1600 }
1601 
TEST(InterpreterInvokeIntrinsic)1602 TEST(InterpreterInvokeIntrinsic) {
1603   HandleAndZoneScope handles;
1604 
1605   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
1606                                0, 2);
1607 
1608   builder.LoadLiteral(Smi::FromInt(15))
1609       .StoreAccumulatorInRegister(Register(0))
1610       .CallRuntime(Runtime::kInlineIsArray, Register(0), 1)
1611       .Return();
1612   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
1613 
1614   InterpreterTester tester(handles.main_isolate(), bytecode_array);
1615   auto callable = tester.GetCallable<>();
1616 
1617   Handle<Object> return_val = callable().ToHandleChecked();
1618   CHECK(return_val->IsBoolean());
1619   CHECK_EQ(return_val->BooleanValue(), false);
1620 }
1621 
TEST(InterpreterFunctionLiteral)1622 TEST(InterpreterFunctionLiteral) {
1623   HandleAndZoneScope handles;
1624 
1625   // Test calling a function literal.
1626   std::string source(
1627       "function " + InterpreterTester::function_name() + "(a) {\n"
1628       "  return (function(x){ return x + 2; })(a);\n"
1629       "}");
1630   InterpreterTester tester(handles.main_isolate(), source.c_str());
1631   auto callable = tester.GetCallable<Handle<Object>>();
1632 
1633   Handle<i::Object> return_val = callable(
1634       Handle<Smi>(Smi::FromInt(3), handles.main_isolate())).ToHandleChecked();
1635   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(5));
1636 }
1637 
1638 
TEST(InterpreterRegExpLiterals)1639 TEST(InterpreterRegExpLiterals) {
1640   HandleAndZoneScope handles;
1641   i::Isolate* isolate = handles.main_isolate();
1642   i::Factory* factory = isolate->factory();
1643 
1644   std::pair<const char*, Handle<Object>> literals[] = {
1645       std::make_pair("return /abd/.exec('cccabbdd');\n",
1646                      factory->null_value()),
1647       std::make_pair("return /ab+d/.exec('cccabbdd')[0];\n",
1648                      factory->NewStringFromStaticChars("abbd")),
1649       std::make_pair("return /AbC/i.exec('ssaBC')[0];\n",
1650                      factory->NewStringFromStaticChars("aBC")),
1651       std::make_pair("return 'ssaBC'.match(/AbC/i)[0];\n",
1652                      factory->NewStringFromStaticChars("aBC")),
1653       std::make_pair("return 'ssaBCtAbC'.match(/(AbC)/gi)[1];\n",
1654                      factory->NewStringFromStaticChars("AbC")),
1655   };
1656 
1657   for (size_t i = 0; i < arraysize(literals); i++) {
1658     std::string source(InterpreterTester::SourceForBody(literals[i].first));
1659     InterpreterTester tester(handles.main_isolate(), source.c_str());
1660     auto callable = tester.GetCallable<>();
1661 
1662     Handle<i::Object> return_value = callable().ToHandleChecked();
1663     CHECK(return_value->SameValue(*literals[i].second));
1664   }
1665 }
1666 
1667 
TEST(InterpreterArrayLiterals)1668 TEST(InterpreterArrayLiterals) {
1669   HandleAndZoneScope handles;
1670   i::Isolate* isolate = handles.main_isolate();
1671   i::Factory* factory = isolate->factory();
1672 
1673   std::pair<const char*, Handle<Object>> literals[] = {
1674       std::make_pair("return [][0];\n",
1675                      factory->undefined_value()),
1676       std::make_pair("return [1, 3, 2][1];\n",
1677                      handle(Smi::FromInt(3), isolate)),
1678       std::make_pair("return ['a', 'b', 'c'][2];\n",
1679                      factory->NewStringFromStaticChars("c")),
1680       std::make_pair("var a = 100; return [a, a + 1, a + 2, a + 3][2];\n",
1681                      handle(Smi::FromInt(102), isolate)),
1682       std::make_pair("return [[1, 2, 3], ['a', 'b', 'c']][1][0];\n",
1683                      factory->NewStringFromStaticChars("a")),
1684       std::make_pair("var t = 't'; return [[t, t + 'est'], [1 + t]][0][1];\n",
1685                      factory->NewStringFromStaticChars("test"))
1686   };
1687 
1688   for (size_t i = 0; i < arraysize(literals); i++) {
1689     std::string source(InterpreterTester::SourceForBody(literals[i].first));
1690     InterpreterTester tester(handles.main_isolate(), source.c_str());
1691     auto callable = tester.GetCallable<>();
1692 
1693     Handle<i::Object> return_value = callable().ToHandleChecked();
1694     CHECK(return_value->SameValue(*literals[i].second));
1695   }
1696 }
1697 
1698 
TEST(InterpreterObjectLiterals)1699 TEST(InterpreterObjectLiterals) {
1700   HandleAndZoneScope handles;
1701   i::Isolate* isolate = handles.main_isolate();
1702   i::Factory* factory = isolate->factory();
1703 
1704   std::pair<const char*, Handle<Object>> literals[] = {
1705       std::make_pair("return { }.name;",
1706                      factory->undefined_value()),
1707       std::make_pair("return { name: 'string', val: 9.2 }.name;",
1708                      factory->NewStringFromStaticChars("string")),
1709       std::make_pair("var a = 15; return { name: 'string', val: a }.val;",
1710                      handle(Smi::FromInt(15), isolate)),
1711       std::make_pair("var a = 5; return { val: a, val: a + 1 }.val;",
1712                      handle(Smi::FromInt(6), isolate)),
1713       std::make_pair("return { func: function() { return 'test' } }.func();",
1714                      factory->NewStringFromStaticChars("test")),
1715       std::make_pair("return { func(a) { return a + 'st'; } }.func('te');",
1716                      factory->NewStringFromStaticChars("test")),
1717       std::make_pair("return { get a() { return 22; } }.a;",
1718                      handle(Smi::FromInt(22), isolate)),
1719       std::make_pair("var a = { get b() { return this.x + 't'; },\n"
1720                      "          set b(val) { this.x = val + 's' } };\n"
1721                      "a.b = 'te';\n"
1722                      "return a.b;",
1723                      factory->NewStringFromStaticChars("test")),
1724       std::make_pair("var a = 123; return { 1: a }[1];",
1725                      handle(Smi::FromInt(123), isolate)),
1726       std::make_pair("return Object.getPrototypeOf({ __proto__: null });",
1727                      factory->null_value()),
1728       std::make_pair("var a = 'test'; return { [a]: 1 }.test;",
1729                      handle(Smi::FromInt(1), isolate)),
1730       std::make_pair("var a = 'test'; return { b: a, [a]: a + 'ing' }['test']",
1731                      factory->NewStringFromStaticChars("testing")),
1732       std::make_pair("var a = 'proto_str';\n"
1733                      "var b = { [a]: 1, __proto__: { var : a } };\n"
1734                      "return Object.getPrototypeOf(b).var",
1735                      factory->NewStringFromStaticChars("proto_str")),
1736       std::make_pair("var n = 'name';\n"
1737                      "return { [n]: 'val', get a() { return 987 } }['a'];",
1738                      handle(Smi::FromInt(987), isolate)),
1739   };
1740 
1741   for (size_t i = 0; i < arraysize(literals); i++) {
1742     std::string source(InterpreterTester::SourceForBody(literals[i].first));
1743     InterpreterTester tester(handles.main_isolate(), source.c_str());
1744     auto callable = tester.GetCallable<>();
1745 
1746     Handle<i::Object> return_value = callable().ToHandleChecked();
1747     CHECK(return_value->SameValue(*literals[i].second));
1748   }
1749 }
1750 
1751 
TEST(InterpreterConstruct)1752 TEST(InterpreterConstruct) {
1753   HandleAndZoneScope handles;
1754 
1755   std::string source(
1756       "function counter() { this.count = 0; }\n"
1757       "function " +
1758       InterpreterTester::function_name() +
1759       "() {\n"
1760       "  var c = new counter();\n"
1761       "  return c.count;\n"
1762       "}");
1763   InterpreterTester tester(handles.main_isolate(), source.c_str());
1764   auto callable = tester.GetCallable<>();
1765 
1766   Handle<Object> return_val = callable().ToHandleChecked();
1767   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(0));
1768 }
1769 
1770 
TEST(InterpreterConstructWithArgument)1771 TEST(InterpreterConstructWithArgument) {
1772   HandleAndZoneScope handles;
1773 
1774   std::string source(
1775       "function counter(arg0) { this.count = 17; this.x = arg0; }\n"
1776       "function " +
1777       InterpreterTester::function_name() +
1778       "() {\n"
1779       "  var c = new counter(3);\n"
1780       "  return c.x;\n"
1781       "}");
1782   InterpreterTester tester(handles.main_isolate(), source.c_str());
1783   auto callable = tester.GetCallable<>();
1784 
1785   Handle<Object> return_val = callable().ToHandleChecked();
1786   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(3));
1787 }
1788 
1789 
TEST(InterpreterConstructWithArguments)1790 TEST(InterpreterConstructWithArguments) {
1791   HandleAndZoneScope handles;
1792 
1793   std::string source(
1794       "function counter(arg0, arg1) {\n"
1795       "  this.count = 7; this.x = arg0; this.y = arg1;\n"
1796       "}\n"
1797       "function " +
1798       InterpreterTester::function_name() +
1799       "() {\n"
1800       "  var c = new counter(3, 5);\n"
1801       "  return c.count + c.x + c.y;\n"
1802       "}");
1803   InterpreterTester tester(handles.main_isolate(), source.c_str());
1804   auto callable = tester.GetCallable<>();
1805 
1806   Handle<Object> return_val = callable().ToHandleChecked();
1807   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(15));
1808 }
1809 
1810 
TEST(InterpreterContextVariables)1811 TEST(InterpreterContextVariables) {
1812   HandleAndZoneScope handles;
1813   i::Isolate* isolate = handles.main_isolate();
1814 
1815   std::ostringstream unique_vars;
1816   for (int i = 0; i < 250; i++) {
1817     unique_vars << "var a" << i << " = 0;";
1818   }
1819   std::pair<std::string, Handle<Object>> context_vars[] = {
1820       std::make_pair("var a; (function() { a = 1; })(); return a;",
1821                      handle(Smi::FromInt(1), isolate)),
1822       std::make_pair("var a = 10; (function() { a; })(); return a;",
1823                      handle(Smi::FromInt(10), isolate)),
1824       std::make_pair("var a = 20; var b = 30;\n"
1825                      "return (function() { return a + b; })();",
1826                      handle(Smi::FromInt(50), isolate)),
1827       std::make_pair("'use strict'; let a = 1;\n"
1828                      "{ let b = 2; return (function() { return a + b; })(); }",
1829                      handle(Smi::FromInt(3), isolate)),
1830       std::make_pair("'use strict'; let a = 10;\n"
1831                      "{ let b = 20; var c = function() { [a, b] };\n"
1832                      "  return a + b; }",
1833                      handle(Smi::FromInt(30), isolate)),
1834       std::make_pair("'use strict';" + unique_vars.str() +
1835                      "eval(); var b = 100; return b;",
1836                      handle(Smi::FromInt(100), isolate)),
1837   };
1838 
1839   for (size_t i = 0; i < arraysize(context_vars); i++) {
1840     std::string source(
1841         InterpreterTester::SourceForBody(context_vars[i].first.c_str()));
1842     InterpreterTester tester(handles.main_isolate(), source.c_str());
1843     auto callable = tester.GetCallable<>();
1844 
1845     Handle<i::Object> return_value = callable().ToHandleChecked();
1846     CHECK(return_value->SameValue(*context_vars[i].second));
1847   }
1848 }
1849 
1850 
TEST(InterpreterContextParameters)1851 TEST(InterpreterContextParameters) {
1852   HandleAndZoneScope handles;
1853   i::Isolate* isolate = handles.main_isolate();
1854 
1855   std::pair<const char*, Handle<Object>> context_params[] = {
1856       std::make_pair("return (function() { return arg1; })();",
1857                      handle(Smi::FromInt(1), isolate)),
1858       std::make_pair("(function() { arg1 = 4; })(); return arg1;",
1859                      handle(Smi::FromInt(4), isolate)),
1860       std::make_pair("(function() { arg3 = arg2 - arg1; })(); return arg3;",
1861                      handle(Smi::FromInt(1), isolate)),
1862   };
1863 
1864   for (size_t i = 0; i < arraysize(context_params); i++) {
1865     std::string source = "function " + InterpreterTester::function_name() +
1866                          "(arg1, arg2, arg3) {" + context_params[i].first + "}";
1867     InterpreterTester tester(handles.main_isolate(), source.c_str());
1868     auto callable =
1869         tester.GetCallable<Handle<Object>, Handle<Object>, Handle<Object>>();
1870 
1871     Handle<Object> a1 = handle(Smi::FromInt(1), isolate);
1872     Handle<Object> a2 = handle(Smi::FromInt(2), isolate);
1873     Handle<Object> a3 = handle(Smi::FromInt(3), isolate);
1874     Handle<i::Object> return_value = callable(a1, a2, a3).ToHandleChecked();
1875     CHECK(return_value->SameValue(*context_params[i].second));
1876   }
1877 }
1878 
1879 
TEST(InterpreterOuterContextVariables)1880 TEST(InterpreterOuterContextVariables) {
1881   HandleAndZoneScope handles;
1882   i::Isolate* isolate = handles.main_isolate();
1883 
1884   std::pair<const char*, Handle<Object>> context_vars[] = {
1885       std::make_pair("return outerVar * innerArg;",
1886                      handle(Smi::FromInt(200), isolate)),
1887       std::make_pair("outerVar = innerArg; return outerVar",
1888                      handle(Smi::FromInt(20), isolate)),
1889   };
1890 
1891   std::string header(
1892       "function Outer() {"
1893       "  var outerVar = 10;"
1894       "  function Inner(innerArg) {"
1895       "    this.innerFunc = function() { ");
1896   std::string footer(
1897       "  }}"
1898       "  this.getInnerFunc = function() { return new Inner(20).innerFunc; }"
1899       "}"
1900       "var f = new Outer().getInnerFunc();");
1901 
1902   for (size_t i = 0; i < arraysize(context_vars); i++) {
1903     std::string source = header + context_vars[i].first + footer;
1904     InterpreterTester tester(handles.main_isolate(), source.c_str(), "*");
1905     auto callable = tester.GetCallable<>();
1906 
1907     Handle<i::Object> return_value = callable().ToHandleChecked();
1908     CHECK(return_value->SameValue(*context_vars[i].second));
1909   }
1910 }
1911 
1912 
TEST(InterpreterComma)1913 TEST(InterpreterComma) {
1914   HandleAndZoneScope handles;
1915   i::Isolate* isolate = handles.main_isolate();
1916   i::Factory* factory = isolate->factory();
1917 
1918   std::pair<const char*, Handle<Object>> literals[] = {
1919       std::make_pair("var a; return 0, a;\n", factory->undefined_value()),
1920       std::make_pair("return 'a', 2.2, 3;\n",
1921                      handle(Smi::FromInt(3), isolate)),
1922       std::make_pair("return 'a', 'b', 'c';\n",
1923                      factory->NewStringFromStaticChars("c")),
1924       std::make_pair("return 3.2, 2.3, 4.5;\n", factory->NewNumber(4.5)),
1925       std::make_pair("var a = 10; return b = a, b = b+1;\n",
1926                      handle(Smi::FromInt(11), isolate)),
1927       std::make_pair("var a = 10; return b = a, b = b+1, b + 10;\n",
1928                      handle(Smi::FromInt(21), isolate))};
1929 
1930   for (size_t i = 0; i < arraysize(literals); i++) {
1931     std::string source(InterpreterTester::SourceForBody(literals[i].first));
1932     InterpreterTester tester(handles.main_isolate(), source.c_str());
1933     auto callable = tester.GetCallable<>();
1934 
1935     Handle<i::Object> return_value = callable().ToHandleChecked();
1936     CHECK(return_value->SameValue(*literals[i].second));
1937   }
1938 }
1939 
1940 
TEST(InterpreterLogicalOr)1941 TEST(InterpreterLogicalOr) {
1942   HandleAndZoneScope handles;
1943   i::Isolate* isolate = handles.main_isolate();
1944   i::Factory* factory = isolate->factory();
1945 
1946   std::pair<const char*, Handle<Object>> literals[] = {
1947       std::make_pair("var a, b; return a || b;\n", factory->undefined_value()),
1948       std::make_pair("var a, b = 10; return a || b;\n",
1949                      handle(Smi::FromInt(10), isolate)),
1950       std::make_pair("var a = '0', b = 10; return a || b;\n",
1951                      factory->NewStringFromStaticChars("0")),
1952       std::make_pair("return 0 || 3.2;\n", factory->NewNumber(3.2)),
1953       std::make_pair("return 'a' || 0;\n",
1954                      factory->NewStringFromStaticChars("a")),
1955       std::make_pair("var a = '0', b = 10; return (a == 0) || b;\n",
1956                      factory->true_value())};
1957 
1958   for (size_t i = 0; i < arraysize(literals); i++) {
1959     std::string source(InterpreterTester::SourceForBody(literals[i].first));
1960     InterpreterTester tester(handles.main_isolate(), source.c_str());
1961     auto callable = tester.GetCallable<>();
1962 
1963     Handle<i::Object> return_value = callable().ToHandleChecked();
1964     CHECK(return_value->SameValue(*literals[i].second));
1965   }
1966 }
1967 
1968 
TEST(InterpreterLogicalAnd)1969 TEST(InterpreterLogicalAnd) {
1970   HandleAndZoneScope handles;
1971   i::Isolate* isolate = handles.main_isolate();
1972   i::Factory* factory = isolate->factory();
1973 
1974   std::pair<const char*, Handle<Object>> literals[] = {
1975       std::make_pair("var a, b = 10; return a && b;\n",
1976                      factory->undefined_value()),
1977       std::make_pair("var a = 0, b = 10; return a && b / a;\n",
1978                      handle(Smi::FromInt(0), isolate)),
1979       std::make_pair("var a = '0', b = 10; return a && b;\n",
1980                      handle(Smi::FromInt(10), isolate)),
1981       std::make_pair("return 0.0 && 3.2;\n", handle(Smi::FromInt(0), isolate)),
1982       std::make_pair("return 'a' && 'b';\n",
1983                      factory->NewStringFromStaticChars("b")),
1984       std::make_pair("return 'a' && 0 || 'b', 'c';\n",
1985                      factory->NewStringFromStaticChars("c")),
1986       std::make_pair("var x = 1, y = 3; return x && 0 + 1 || y;\n",
1987                      handle(Smi::FromInt(1), isolate)),
1988       std::make_pair("var x = 1, y = 3; return (x == 1) && (3 == 3) || y;\n",
1989                      factory->true_value())};
1990 
1991   for (size_t i = 0; i < arraysize(literals); i++) {
1992     std::string source(InterpreterTester::SourceForBody(literals[i].first));
1993     InterpreterTester tester(handles.main_isolate(), source.c_str());
1994     auto callable = tester.GetCallable<>();
1995 
1996     Handle<i::Object> return_value = callable().ToHandleChecked();
1997     CHECK(return_value->SameValue(*literals[i].second));
1998   }
1999 }
2000 
2001 
TEST(InterpreterTryCatch)2002 TEST(InterpreterTryCatch) {
2003   HandleAndZoneScope handles;
2004   i::Isolate* isolate = handles.main_isolate();
2005 
2006   std::pair<const char*, Handle<Object>> catches[] = {
2007       std::make_pair("var a = 1; try { a = 2 } catch(e) { a = 3 }; return a;",
2008                      handle(Smi::FromInt(2), isolate)),
2009       std::make_pair("var a; try { undef.x } catch(e) { a = 2 }; return a;",
2010                      handle(Smi::FromInt(2), isolate)),
2011       std::make_pair("var a; try { throw 1 } catch(e) { a = e + 2 }; return a;",
2012                      handle(Smi::FromInt(3), isolate)),
2013       std::make_pair("var a; try { throw 1 } catch(e) { a = e + 2 };"
2014                      "       try { throw a } catch(e) { a = e + 3 }; return a;",
2015                      handle(Smi::FromInt(6), isolate)),
2016   };
2017 
2018   for (size_t i = 0; i < arraysize(catches); i++) {
2019     std::string source(InterpreterTester::SourceForBody(catches[i].first));
2020     InterpreterTester tester(handles.main_isolate(), source.c_str());
2021     auto callable = tester.GetCallable<>();
2022 
2023     Handle<i::Object> return_value = callable().ToHandleChecked();
2024     CHECK(return_value->SameValue(*catches[i].second));
2025   }
2026 }
2027 
2028 
TEST(InterpreterTryFinally)2029 TEST(InterpreterTryFinally) {
2030   HandleAndZoneScope handles;
2031   i::Isolate* isolate = handles.main_isolate();
2032   i::Factory* factory = isolate->factory();
2033 
2034   std::pair<const char*, Handle<Object>> finallies[] = {
2035       std::make_pair(
2036           "var a = 1; try { a = a + 1; } finally { a = a + 2; }; return a;",
2037           factory->NewStringFromStaticChars("R4")),
2038       std::make_pair(
2039           "var a = 1; try { a = 2; return 23; } finally { a = 3 }; return a;",
2040           factory->NewStringFromStaticChars("R23")),
2041       std::make_pair(
2042           "var a = 1; try { a = 2; throw 23; } finally { a = 3 }; return a;",
2043           factory->NewStringFromStaticChars("E23")),
2044       std::make_pair(
2045           "var a = 1; try { a = 2; throw 23; } finally { return a; };",
2046           factory->NewStringFromStaticChars("R2")),
2047       std::make_pair(
2048           "var a = 1; try { a = 2; throw 23; } finally { throw 42; };",
2049           factory->NewStringFromStaticChars("E42")),
2050       std::make_pair("var a = 1; for (var i = 10; i < 20; i += 5) {"
2051                      "  try { a = 2; break; } finally { a = 3; }"
2052                      "} return a + i;",
2053                      factory->NewStringFromStaticChars("R13")),
2054       std::make_pair("var a = 1; for (var i = 10; i < 20; i += 5) {"
2055                      "  try { a = 2; continue; } finally { a = 3; }"
2056                      "} return a + i;",
2057                      factory->NewStringFromStaticChars("R23")),
2058       std::make_pair("var a = 1; try { a = 2;"
2059                      "  try { a = 3; throw 23; } finally { a = 4; }"
2060                      "} catch(e) { a = a + e; } return a;",
2061                      factory->NewStringFromStaticChars("R27")),
2062       std::make_pair("var func_name;"
2063                      "function tcf2(a) {"
2064                      "  try { throw new Error('boom');} "
2065                      "  catch(e) {return 153; } "
2066                      "  finally {func_name = tcf2.name;}"
2067                      "}"
2068                      "tcf2();"
2069                      "return func_name;",
2070                      factory->NewStringFromStaticChars("Rtcf2")),
2071   };
2072 
2073   const char* try_wrapper =
2074       "(function() { try { return 'R' + f() } catch(e) { return 'E' + e }})()";
2075 
2076   for (size_t i = 0; i < arraysize(finallies); i++) {
2077     std::string source(InterpreterTester::SourceForBody(finallies[i].first));
2078     InterpreterTester tester(handles.main_isolate(), source.c_str());
2079     tester.GetCallable<>();
2080     Handle<Object> wrapped = v8::Utils::OpenHandle(*CompileRun(try_wrapper));
2081     CHECK(wrapped->SameValue(*finallies[i].second));
2082   }
2083 }
2084 
2085 
TEST(InterpreterThrow)2086 TEST(InterpreterThrow) {
2087   HandleAndZoneScope handles;
2088   i::Isolate* isolate = handles.main_isolate();
2089   i::Factory* factory = isolate->factory();
2090 
2091   std::pair<const char*, Handle<Object>> throws[] = {
2092       std::make_pair("throw undefined;\n",
2093                      factory->undefined_value()),
2094       std::make_pair("throw 1;\n",
2095                      handle(Smi::FromInt(1), isolate)),
2096       std::make_pair("throw 'Error';\n",
2097                      factory->NewStringFromStaticChars("Error")),
2098       std::make_pair("var a = true; if (a) { throw 'Error'; }\n",
2099                      factory->NewStringFromStaticChars("Error")),
2100       std::make_pair("var a = false; if (a) { throw 'Error'; }\n",
2101                      factory->undefined_value()),
2102       std::make_pair("throw 'Error1'; throw 'Error2'\n",
2103                      factory->NewStringFromStaticChars("Error1")),
2104   };
2105 
2106   const char* try_wrapper =
2107       "(function() { try { f(); } catch(e) { return e; }})()";
2108 
2109   for (size_t i = 0; i < arraysize(throws); i++) {
2110     std::string source(InterpreterTester::SourceForBody(throws[i].first));
2111     InterpreterTester tester(handles.main_isolate(), source.c_str());
2112     tester.GetCallable<>();
2113     Handle<Object> thrown_obj = v8::Utils::OpenHandle(*CompileRun(try_wrapper));
2114     CHECK(thrown_obj->SameValue(*throws[i].second));
2115   }
2116 }
2117 
2118 
TEST(InterpreterCountOperators)2119 TEST(InterpreterCountOperators) {
2120   HandleAndZoneScope handles;
2121   i::Isolate* isolate = handles.main_isolate();
2122   i::Factory* factory = isolate->factory();
2123 
2124   std::pair<const char*, Handle<Object>> count_ops[] = {
2125       std::make_pair("var a = 1; return ++a;",
2126                      handle(Smi::FromInt(2), isolate)),
2127       std::make_pair("var a = 1; return a++;",
2128                      handle(Smi::FromInt(1), isolate)),
2129       std::make_pair("var a = 5; return --a;",
2130                      handle(Smi::FromInt(4), isolate)),
2131       std::make_pair("var a = 5; return a--;",
2132                      handle(Smi::FromInt(5), isolate)),
2133       std::make_pair("var a = 5.2; return --a;",
2134                      factory->NewHeapNumber(4.2)),
2135       std::make_pair("var a = 'string'; return ++a;",
2136                      factory->nan_value()),
2137       std::make_pair("var a = 'string'; return a--;",
2138                      factory->nan_value()),
2139       std::make_pair("var a = true; return ++a;",
2140                      handle(Smi::FromInt(2), isolate)),
2141       std::make_pair("var a = false; return a--;",
2142                      handle(Smi::FromInt(0), isolate)),
2143       std::make_pair("var a = { val: 11 }; return ++a.val;",
2144                      handle(Smi::FromInt(12), isolate)),
2145       std::make_pair("var a = { val: 11 }; return a.val--;",
2146                      handle(Smi::FromInt(11), isolate)),
2147       std::make_pair("var a = { val: 11 }; return ++a.val;",
2148                      handle(Smi::FromInt(12), isolate)),
2149       std::make_pair("var name = 'val'; var a = { val: 22 }; return --a[name];",
2150                      handle(Smi::FromInt(21), isolate)),
2151       std::make_pair("var name = 'val'; var a = { val: 22 }; return a[name]++;",
2152                      handle(Smi::FromInt(22), isolate)),
2153       std::make_pair("var a = 1; (function() { a = 2 })(); return ++a;",
2154                      handle(Smi::FromInt(3), isolate)),
2155       std::make_pair("var a = 1; (function() { a = 2 })(); return a--;",
2156                      handle(Smi::FromInt(2), isolate)),
2157       std::make_pair("var i = 5; while(i--) {}; return i;",
2158                      handle(Smi::FromInt(-1), isolate)),
2159       std::make_pair("var i = 1; if(i--) { return 1; } else { return 2; };",
2160                      handle(Smi::FromInt(1), isolate)),
2161       std::make_pair("var i = -2; do {} while(i++) {}; return i;",
2162                       handle(Smi::FromInt(1), isolate)),
2163       std::make_pair("var i = -1; for(; i++; ) {}; return i",
2164                       handle(Smi::FromInt(1), isolate)),
2165       std::make_pair("var i = 20; switch(i++) {\n"
2166                      "  case 20: return 1;\n"
2167                      "  default: return 2;\n"
2168                      "}",
2169                      handle(Smi::FromInt(1), isolate)),
2170   };
2171 
2172   for (size_t i = 0; i < arraysize(count_ops); i++) {
2173     std::string source(InterpreterTester::SourceForBody(count_ops[i].first));
2174     InterpreterTester tester(handles.main_isolate(), source.c_str());
2175     auto callable = tester.GetCallable<>();
2176 
2177     Handle<i::Object> return_value = callable().ToHandleChecked();
2178     CHECK(return_value->SameValue(*count_ops[i].second));
2179   }
2180 }
2181 
2182 
TEST(InterpreterGlobalCountOperators)2183 TEST(InterpreterGlobalCountOperators) {
2184   HandleAndZoneScope handles;
2185   i::Isolate* isolate = handles.main_isolate();
2186 
2187   std::pair<const char*, Handle<Object>> count_ops[] = {
2188       std::make_pair("var global = 100;function f(){ return ++global; }",
2189                      handle(Smi::FromInt(101), isolate)),
2190       std::make_pair("var global = 100; function f(){ return --global; }",
2191                      handle(Smi::FromInt(99), isolate)),
2192       std::make_pair("var global = 100; function f(){ return global++; }",
2193                      handle(Smi::FromInt(100), isolate)),
2194       std::make_pair("unallocated = 200; function f(){ return ++unallocated; }",
2195                      handle(Smi::FromInt(201), isolate)),
2196       std::make_pair("unallocated = 200; function f(){ return --unallocated; }",
2197                      handle(Smi::FromInt(199), isolate)),
2198       std::make_pair("unallocated = 200; function f(){ return unallocated++; }",
2199                      handle(Smi::FromInt(200), isolate)),
2200   };
2201 
2202   for (size_t i = 0; i < arraysize(count_ops); i++) {
2203     InterpreterTester tester(handles.main_isolate(), count_ops[i].first);
2204     auto callable = tester.GetCallable<>();
2205 
2206     Handle<i::Object> return_value = callable().ToHandleChecked();
2207     CHECK(return_value->SameValue(*count_ops[i].second));
2208   }
2209 }
2210 
2211 
TEST(InterpreterCompoundExpressions)2212 TEST(InterpreterCompoundExpressions) {
2213   HandleAndZoneScope handles;
2214   i::Isolate* isolate = handles.main_isolate();
2215   i::Factory* factory = isolate->factory();
2216 
2217   std::pair<const char*, Handle<Object>> compound_expr[] = {
2218       std::make_pair("var a = 1; a += 2; return a;",
2219                      Handle<Object>(Smi::FromInt(3), isolate)),
2220       std::make_pair("var a = 10; a /= 2; return a;",
2221                      Handle<Object>(Smi::FromInt(5), isolate)),
2222       std::make_pair("var a = 'test'; a += 'ing'; return a;",
2223                      factory->NewStringFromStaticChars("testing")),
2224       std::make_pair("var a = { val: 2 }; a.val *= 2; return a.val;",
2225                      Handle<Object>(Smi::FromInt(4), isolate)),
2226       std::make_pair("var a = 1; (function f() { a = 2; })(); a += 24;"
2227                      "return a;",
2228                      Handle<Object>(Smi::FromInt(26), isolate)),
2229   };
2230 
2231   for (size_t i = 0; i < arraysize(compound_expr); i++) {
2232     std::string source(
2233         InterpreterTester::SourceForBody(compound_expr[i].first));
2234     InterpreterTester tester(handles.main_isolate(), source.c_str());
2235     auto callable = tester.GetCallable<>();
2236 
2237     Handle<i::Object> return_value = callable().ToHandleChecked();
2238     CHECK(return_value->SameValue(*compound_expr[i].second));
2239   }
2240 }
2241 
2242 
TEST(InterpreterGlobalCompoundExpressions)2243 TEST(InterpreterGlobalCompoundExpressions) {
2244   HandleAndZoneScope handles;
2245   i::Isolate* isolate = handles.main_isolate();
2246 
2247   std::pair<const char*, Handle<Object>> compound_expr[2] = {
2248       std::make_pair("var global = 100;"
2249                      "function f() { global += 20; return global; }",
2250                      Handle<Object>(Smi::FromInt(120), isolate)),
2251       std::make_pair("unallocated = 100;"
2252                      "function f() { unallocated -= 20; return unallocated; }",
2253                      Handle<Object>(Smi::FromInt(80), isolate)),
2254   };
2255 
2256   for (size_t i = 0; i < arraysize(compound_expr); i++) {
2257     InterpreterTester tester(handles.main_isolate(), compound_expr[i].first);
2258     auto callable = tester.GetCallable<>();
2259 
2260     Handle<i::Object> return_value = callable().ToHandleChecked();
2261     CHECK(return_value->SameValue(*compound_expr[i].second));
2262   }
2263 }
2264 
2265 
TEST(InterpreterCreateArguments)2266 TEST(InterpreterCreateArguments) {
2267   HandleAndZoneScope handles;
2268   i::Isolate* isolate = handles.main_isolate();
2269   i::Factory* factory = isolate->factory();
2270 
2271   std::pair<const char*, int> create_args[] = {
2272       std::make_pair("function f() { return arguments[0]; }", 0),
2273       std::make_pair("function f(a) { return arguments[0]; }", 0),
2274       std::make_pair("function f() { return arguments[2]; }", 2),
2275       std::make_pair("function f(a) { return arguments[2]; }", 2),
2276       std::make_pair("function f(a, b, c, d) { return arguments[2]; }", 2),
2277       std::make_pair("function f(a) {"
2278                      "'use strict'; return arguments[0]; }",
2279                      0),
2280       std::make_pair("function f(a, b, c, d) {"
2281                      "'use strict'; return arguments[2]; }",
2282                      2),
2283       // Check arguments are mapped in sloppy mode and unmapped in strict.
2284       std::make_pair("function f(a, b, c, d) {"
2285                      "  c = b; return arguments[2]; }",
2286                      1),
2287       std::make_pair("function f(a, b, c, d) {"
2288                      "  'use strict'; c = b; return arguments[2]; }",
2289                      2),
2290       // Check arguments for duplicate parameters in sloppy mode.
2291       std::make_pair("function f(a, a, b) { return arguments[1]; }", 1),
2292       // check rest parameters
2293       std::make_pair("function f(...restArray) { return restArray[0]; }", 0),
2294       std::make_pair("function f(a, ...restArray) { return restArray[0]; }", 1),
2295       std::make_pair("function f(a, ...restArray) { return arguments[0]; }", 0),
2296       std::make_pair("function f(a, ...restArray) { return arguments[1]; }", 1),
2297       std::make_pair("function f(a, ...restArray) { return restArray[1]; }", 2),
2298       std::make_pair("function f(a, ...arguments) { return arguments[0]; }", 1),
2299       std::make_pair("function f(a, b, ...restArray) { return restArray[0]; }",
2300                      2),
2301   };
2302 
2303   // Test passing no arguments.
2304   for (size_t i = 0; i < arraysize(create_args); i++) {
2305     InterpreterTester tester(handles.main_isolate(), create_args[i].first);
2306     auto callable = tester.GetCallable<>();
2307     Handle<Object> return_val = callable().ToHandleChecked();
2308     CHECK(return_val.is_identical_to(factory->undefined_value()));
2309   }
2310 
2311   // Test passing one argument.
2312   for (size_t i = 0; i < arraysize(create_args); i++) {
2313     InterpreterTester tester(handles.main_isolate(), create_args[i].first);
2314     auto callable = tester.GetCallable<Handle<Object>>();
2315     Handle<Object> return_val =
2316         callable(handle(Smi::FromInt(40), isolate)).ToHandleChecked();
2317     if (create_args[i].second == 0) {
2318       CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(40));
2319     } else {
2320       CHECK(return_val.is_identical_to(factory->undefined_value()));
2321     }
2322   }
2323 
2324   // Test passing three argument.
2325   for (size_t i = 0; i < arraysize(create_args); i++) {
2326     Handle<Object> args[3] = {
2327         handle(Smi::FromInt(40), isolate),
2328         handle(Smi::FromInt(60), isolate),
2329         handle(Smi::FromInt(80), isolate),
2330     };
2331 
2332     InterpreterTester tester(handles.main_isolate(), create_args[i].first);
2333     auto callable =
2334         tester.GetCallable<Handle<Object>, Handle<Object>, Handle<Object>>();
2335     Handle<Object> return_val =
2336         callable(args[0], args[1], args[2]).ToHandleChecked();
2337     CHECK(return_val->SameValue(*args[create_args[i].second]));
2338   }
2339 }
2340 
2341 
TEST(InterpreterConditional)2342 TEST(InterpreterConditional) {
2343   HandleAndZoneScope handles;
2344   i::Isolate* isolate = handles.main_isolate();
2345 
2346   std::pair<const char*, Handle<Object>> conditional[] = {
2347       std::make_pair("return true ? 2 : 3;",
2348                      handle(Smi::FromInt(2), isolate)),
2349       std::make_pair("return false ? 2 : 3;",
2350                      handle(Smi::FromInt(3), isolate)),
2351       std::make_pair("var a = 1; return a ? 20 : 30;",
2352                      handle(Smi::FromInt(20), isolate)),
2353       std::make_pair("var a = 1; return a ? 20 : 30;",
2354                      handle(Smi::FromInt(20), isolate)),
2355       std::make_pair("var a = 'string'; return a ? 20 : 30;",
2356                      handle(Smi::FromInt(20), isolate)),
2357       std::make_pair("var a = undefined; return a ? 20 : 30;",
2358                      handle(Smi::FromInt(30), isolate)),
2359       std::make_pair("return 1 ? 2 ? 3 : 4 : 5;",
2360                      handle(Smi::FromInt(3), isolate)),
2361       std::make_pair("return 0 ? 2 ? 3 : 4 : 5;",
2362                      handle(Smi::FromInt(5), isolate)),
2363   };
2364 
2365   for (size_t i = 0; i < arraysize(conditional); i++) {
2366     std::string source(InterpreterTester::SourceForBody(conditional[i].first));
2367     InterpreterTester tester(handles.main_isolate(), source.c_str());
2368     auto callable = tester.GetCallable<>();
2369 
2370     Handle<i::Object> return_value = callable().ToHandleChecked();
2371     CHECK(return_value->SameValue(*conditional[i].second));
2372   }
2373 }
2374 
2375 
TEST(InterpreterDelete)2376 TEST(InterpreterDelete) {
2377   HandleAndZoneScope handles;
2378   i::Isolate* isolate = handles.main_isolate();
2379   i::Factory* factory = isolate->factory();
2380 
2381   // Tests for delete for local variables that work both in strict
2382   // and sloppy modes
2383   std::pair<const char*, Handle<Object>> test_delete[] = {
2384       std::make_pair(
2385           "var a = { x:10, y:'abc', z:30.2}; delete a.x; return a.x;\n",
2386           factory->undefined_value()),
2387       std::make_pair(
2388           "var b = { x:10, y:'abc', z:30.2}; delete b.x; return b.y;\n",
2389           factory->NewStringFromStaticChars("abc")),
2390       std::make_pair("var c = { x:10, y:'abc', z:30.2}; var d = c; delete d.x; "
2391                      "return c.x;\n",
2392                      factory->undefined_value()),
2393       std::make_pair("var e = { x:10, y:'abc', z:30.2}; var g = e; delete g.x; "
2394                      "return e.y;\n",
2395                      factory->NewStringFromStaticChars("abc")),
2396       std::make_pair("var a = { x:10, y:'abc', z:30.2};\n"
2397                      "var b = a;"
2398                      "delete b.x;"
2399                      "return b.x;\n",
2400                      factory->undefined_value()),
2401       std::make_pair("var a = {1:10};\n"
2402                      "(function f1() {return a;});"
2403                      "return delete a[1];",
2404                      factory->ToBoolean(true)),
2405       std::make_pair("return delete this;", factory->ToBoolean(true)),
2406       std::make_pair("return delete 'test';", factory->ToBoolean(true))};
2407 
2408   // Test delete in sloppy mode
2409   for (size_t i = 0; i < arraysize(test_delete); i++) {
2410     std::string source(InterpreterTester::SourceForBody(test_delete[i].first));
2411     InterpreterTester tester(handles.main_isolate(), source.c_str());
2412     auto callable = tester.GetCallable<>();
2413 
2414     Handle<i::Object> return_value = callable().ToHandleChecked();
2415     CHECK(return_value->SameValue(*test_delete[i].second));
2416   }
2417 
2418   // Test delete in strict mode
2419   for (size_t i = 0; i < arraysize(test_delete); i++) {
2420     std::string strict_test =
2421         "'use strict'; " + std::string(test_delete[i].first);
2422     std::string source(InterpreterTester::SourceForBody(strict_test.c_str()));
2423     InterpreterTester tester(handles.main_isolate(), source.c_str());
2424     auto callable = tester.GetCallable<>();
2425 
2426     Handle<i::Object> return_value = callable().ToHandleChecked();
2427     CHECK(return_value->SameValue(*test_delete[i].second));
2428   }
2429 }
2430 
2431 
TEST(InterpreterDeleteSloppyUnqualifiedIdentifier)2432 TEST(InterpreterDeleteSloppyUnqualifiedIdentifier) {
2433   HandleAndZoneScope handles;
2434   i::Isolate* isolate = handles.main_isolate();
2435   i::Factory* factory = isolate->factory();
2436 
2437   // These tests generate a syntax error for strict mode. We don't
2438   // test for it here.
2439   std::pair<const char*, Handle<Object>> test_delete[] = {
2440       std::make_pair("var sloppy_a = { x:10, y:'abc'};\n"
2441                      "var sloppy_b = delete sloppy_a;\n"
2442                      "if (delete sloppy_a) {\n"
2443                      "  return undefined;\n"
2444                      "} else {\n"
2445                      "  return sloppy_a.x;\n"
2446                      "}\n",
2447                      Handle<Object>(Smi::FromInt(10), isolate)),
2448       // TODO(mythria) When try-catch is implemented change the tests to check
2449       // if delete actually deletes
2450       std::make_pair("sloppy_a = { x:10, y:'abc'};\n"
2451                      "var sloppy_b = delete sloppy_a;\n"
2452                      // "try{return a.x;} catch(e) {return b;}\n"
2453                      "return sloppy_b;",
2454                      factory->ToBoolean(true)),
2455       std::make_pair("sloppy_a = { x:10, y:'abc'};\n"
2456                      "var sloppy_b = delete sloppy_c;\n"
2457                      "return sloppy_b;",
2458                      factory->ToBoolean(true))};
2459 
2460   for (size_t i = 0; i < arraysize(test_delete); i++) {
2461     std::string source(InterpreterTester::SourceForBody(test_delete[i].first));
2462     InterpreterTester tester(handles.main_isolate(), source.c_str());
2463     auto callable = tester.GetCallable<>();
2464 
2465     Handle<i::Object> return_value = callable().ToHandleChecked();
2466     CHECK(return_value->SameValue(*test_delete[i].second));
2467   }
2468 }
2469 
2470 
TEST(InterpreterGlobalDelete)2471 TEST(InterpreterGlobalDelete) {
2472   HandleAndZoneScope handles;
2473   i::Isolate* isolate = handles.main_isolate();
2474   i::Factory* factory = isolate->factory();
2475 
2476   std::pair<const char*, Handle<Object>> test_global_delete[] = {
2477       std::make_pair("var a = { x:10, y:'abc', z:30.2 };\n"
2478                      "function f() {\n"
2479                      "  delete a.x;\n"
2480                      "  return a.x;\n"
2481                      "}\n"
2482                      "f();\n",
2483                      factory->undefined_value()),
2484       std::make_pair("var b = {1:10, 2:'abc', 3:30.2 };\n"
2485                      "function f() {\n"
2486                      "  delete b[2];\n"
2487                      "  return b[1];\n"
2488                      " }\n"
2489                      "f();\n",
2490                      Handle<Object>(Smi::FromInt(10), isolate)),
2491       std::make_pair("var c = { x:10, y:'abc', z:30.2 };\n"
2492                      "function f() {\n"
2493                      "   var d = c;\n"
2494                      "   delete d.y;\n"
2495                      "   return d.x;\n"
2496                      "}\n"
2497                      "f();\n",
2498                      Handle<Object>(Smi::FromInt(10), isolate)),
2499       std::make_pair("e = { x:10, y:'abc' };\n"
2500                      "function f() {\n"
2501                      "  return delete e;\n"
2502                      "}\n"
2503                      "f();\n",
2504                      factory->ToBoolean(true)),
2505       std::make_pair("var g = { x:10, y:'abc' };\n"
2506                      "function f() {\n"
2507                      "  return delete g;\n"
2508                      "}\n"
2509                      "f();\n",
2510                      factory->ToBoolean(false)),
2511       std::make_pair("function f() {\n"
2512                      "  var obj = {h:10, f1() {return delete this;}};\n"
2513                      "  return obj.f1();\n"
2514                      "}\n"
2515                      "f();",
2516                      factory->ToBoolean(true)),
2517       std::make_pair("function f() {\n"
2518                      "  var obj = {h:10,\n"
2519                      "             f1() {\n"
2520                      "              'use strict';\n"
2521                      "              return delete this.h;}};\n"
2522                      "  return obj.f1();\n"
2523                      "}\n"
2524                      "f();",
2525                      factory->ToBoolean(true))};
2526 
2527   for (size_t i = 0; i < arraysize(test_global_delete); i++) {
2528     InterpreterTester tester(handles.main_isolate(),
2529                              test_global_delete[i].first);
2530     auto callable = tester.GetCallable<>();
2531 
2532     Handle<i::Object> return_value = callable().ToHandleChecked();
2533     CHECK(return_value->SameValue(*test_global_delete[i].second));
2534   }
2535 }
2536 
2537 
TEST(InterpreterBasicLoops)2538 TEST(InterpreterBasicLoops) {
2539   HandleAndZoneScope handles;
2540   i::Isolate* isolate = handles.main_isolate();
2541   i::Factory* factory = isolate->factory();
2542 
2543   std::pair<const char*, Handle<Object>> loops[] = {
2544       std::make_pair("var a = 10; var b = 1;\n"
2545                      "while (a) {\n"
2546                      "  b = b * 2;\n"
2547                      "  a = a - 1;\n"
2548                      "};\n"
2549                      "return b;\n",
2550                      factory->NewHeapNumber(1024)),
2551       std::make_pair("var a = 1; var b = 1;\n"
2552                      "do {\n"
2553                      "  b = b * 2;\n"
2554                      "  --a;\n"
2555                      "} while(a);\n"
2556                      "return b;\n",
2557                      handle(Smi::FromInt(2), isolate)),
2558       std::make_pair("var b = 1;\n"
2559                      "for ( var a = 10; a; a--) {\n"
2560                      "  b *= 2;\n"
2561                      "}\n"
2562                      "return b;",
2563                      factory->NewHeapNumber(1024)),
2564       std::make_pair("var a = 10; var b = 1;\n"
2565                      "while (a > 0) {\n"
2566                      "  b = b * 2;\n"
2567                      "  a = a - 1;\n"
2568                      "};\n"
2569                      "return b;\n",
2570                      factory->NewHeapNumber(1024)),
2571       std::make_pair("var a = 1; var b = 1;\n"
2572                      "do {\n"
2573                      "  b = b * 2;\n"
2574                      "  --a;\n"
2575                      "} while(a);\n"
2576                      "return b;\n",
2577                      handle(Smi::FromInt(2), isolate)),
2578       std::make_pair("var b = 1;\n"
2579                      "for ( var a = 10; a > 0; a--) {\n"
2580                      "  b *= 2;\n"
2581                      "}\n"
2582                      "return b;",
2583                      factory->NewHeapNumber(1024)),
2584       std::make_pair("var a = 10; var b = 1;\n"
2585                      "while (false) {\n"
2586                      "  b = b * 2;\n"
2587                      "  a = a - 1;\n"
2588                      "}\n"
2589                      "return b;\n",
2590                      Handle<Object>(Smi::FromInt(1), isolate)),
2591       std::make_pair("var a = 10; var b = 1;\n"
2592                      "while (true) {\n"
2593                      "  b = b * 2;\n"
2594                      "  a = a - 1;\n"
2595                      "  if (a == 0) break;"
2596                      "  continue;"
2597                      "}\n"
2598                      "return b;\n",
2599                      factory->NewHeapNumber(1024)),
2600       std::make_pair("var a = 10; var b = 1;\n"
2601                      "do {\n"
2602                      "  b = b * 2;\n"
2603                      "  a = a - 1;\n"
2604                      "  if (a == 0) break;"
2605                      "} while(true);\n"
2606                      "return b;\n",
2607                      factory->NewHeapNumber(1024)),
2608       std::make_pair("var a = 10; var b = 1;\n"
2609                      "do {\n"
2610                      "  b = b * 2;\n"
2611                      "  a = a - 1;\n"
2612                      "  if (a == 0) break;"
2613                      "} while(false);\n"
2614                      "return b;\n",
2615                      Handle<Object>(Smi::FromInt(2), isolate)),
2616       std::make_pair("var a = 10; var b = 1;\n"
2617                      "for ( a = 1, b = 30; false; ) {\n"
2618                      "  b = b * 2;\n"
2619                      "}\n"
2620                      "return b;\n",
2621                      Handle<Object>(Smi::FromInt(30), isolate))};
2622 
2623   for (size_t i = 0; i < arraysize(loops); i++) {
2624     std::string source(InterpreterTester::SourceForBody(loops[i].first));
2625     InterpreterTester tester(handles.main_isolate(), source.c_str());
2626     auto callable = tester.GetCallable<>();
2627 
2628     Handle<i::Object> return_value = callable().ToHandleChecked();
2629     CHECK(return_value->SameValue(*loops[i].second));
2630   }
2631 }
2632 
2633 
TEST(InterpreterForIn)2634 TEST(InterpreterForIn) {
2635   std::pair<const char*, int> for_in_samples[] = {
2636       {"var r = -1;\n"
2637        "for (var a in null) { r = a; }\n"
2638        "return r;\n",
2639        -1},
2640       {"var r = -1;\n"
2641        "for (var a in undefined) { r = a; }\n"
2642        "return r;\n",
2643        -1},
2644       {"var r = 0;\n"
2645        "for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
2646        "return r;\n",
2647        0xf},
2648       {"var r = 0;\n"
2649        "for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
2650        "var r = 0;\n"
2651        "for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
2652        "return r;\n",
2653        0xf},
2654       {"var r = 0;\n"
2655        "for (var a in 'foobar') { r = r + (1 << a); }\n"
2656        "return r;\n",
2657        0x3f},
2658       {"var r = 0;\n"
2659        "for (var a in {1:0, 10:1, 100:2, 1000:3}) {\n"
2660        "  r = r + Number(a);\n"
2661        " }\n"
2662        " return r;\n",
2663        1111},
2664       {"var r = 0;\n"
2665        "var data = {1:0, 10:1, 100:2, 1000:3};\n"
2666        "for (var a in data) {\n"
2667        "  if (a == 1) delete data[1];\n"
2668        "  r = r + Number(a);\n"
2669        " }\n"
2670        " return r;\n",
2671        1111},
2672       {"var r = 0;\n"
2673        "var data = {1:0, 10:1, 100:2, 1000:3};\n"
2674        "for (var a in data) {\n"
2675        "  if (a == 10) delete data[100];\n"
2676        "  r = r + Number(a);\n"
2677        " }\n"
2678        " return r;\n",
2679        1011},
2680       {"var r = 0;\n"
2681        "var data = {1:0, 10:1, 100:2, 1000:3};\n"
2682        "for (var a in data) {\n"
2683        "  if (a == 10) data[10000] = 4;\n"
2684        "  r = r + Number(a);\n"
2685        " }\n"
2686        " return r;\n",
2687        1111},
2688       {"var r = 0;\n"
2689        "var input = 'foobar';\n"
2690        "for (var a in input) {\n"
2691        "  if (input[a] == 'b') break;\n"
2692        "  r = r + (1 << a);\n"
2693        "}\n"
2694        "return r;\n",
2695        0x7},
2696       {"var r = 0;\n"
2697        "var input = 'foobar';\n"
2698        "for (var a in input) {\n"
2699        " if (input[a] == 'b') continue;\n"
2700        " r = r + (1 << a);\n"
2701        "}\n"
2702        "return r;\n",
2703        0x37},
2704       {"var r = 0;\n"
2705        "var data = {1:0, 10:1, 100:2, 1000:3};\n"
2706        "for (var a in data) {\n"
2707        "  if (a == 10) {\n"
2708        "     data[10000] = 4;\n"
2709        "  }\n"
2710        "  r = r + Number(a);\n"
2711        "}\n"
2712        "return r;\n",
2713        1111},
2714       {"var r = [ 3 ];\n"
2715        "var data = {1:0, 10:1, 100:2, 1000:3};\n"
2716        "for (r[10] in data) {\n"
2717        "}\n"
2718        "return Number(r[10]);\n",
2719        1000},
2720       {"var r = [ 3 ];\n"
2721        "var data = {1:0, 10:1, 100:2, 1000:3};\n"
2722        "for (r['100'] in data) {\n"
2723        "}\n"
2724        "return Number(r['100']);\n",
2725        1000},
2726       {"var obj = {}\n"
2727        "var descObj = new Boolean(false);\n"
2728        "var accessed = 0;\n"
2729        "descObj.enumerable = true;\n"
2730        "Object.defineProperties(obj, { prop:descObj });\n"
2731        "for (var p in obj) {\n"
2732        "  if (p === 'prop') { accessed = 1; }\n"
2733        "}\n"
2734        "return accessed;",
2735        1},
2736       {"var appointment = {};\n"
2737        "Object.defineProperty(appointment, 'startTime', {\n"
2738        "    value: 1001,\n"
2739        "    writable: false,\n"
2740        "    enumerable: false,\n"
2741        "    configurable: true\n"
2742        "});\n"
2743        "Object.defineProperty(appointment, 'name', {\n"
2744        "    value: 'NAME',\n"
2745        "    writable: false,\n"
2746        "    enumerable: false,\n"
2747        "    configurable: true\n"
2748        "});\n"
2749        "var meeting = Object.create(appointment);\n"
2750        "Object.defineProperty(meeting, 'conferenceCall', {\n"
2751        "    value: 'In-person meeting',\n"
2752        "    writable: false,\n"
2753        "    enumerable: false,\n"
2754        "    configurable: true\n"
2755        "});\n"
2756        "\n"
2757        "var teamMeeting = Object.create(meeting);\n"
2758        "\n"
2759        "var flags = 0;\n"
2760        "for (var p in teamMeeting) {\n"
2761        "    if (p === 'startTime') {\n"
2762        "        flags |= 1;\n"
2763        "    }\n"
2764        "    if (p === 'name') {\n"
2765        "        flags |= 2;\n"
2766        "    }\n"
2767        "    if (p === 'conferenceCall') {\n"
2768        "        flags |= 4;\n"
2769        "    }\n"
2770        "}\n"
2771        "\n"
2772        "var hasOwnProperty = !teamMeeting.hasOwnProperty('name') &&\n"
2773        "    !teamMeeting.hasOwnProperty('startTime') &&\n"
2774        "    !teamMeeting.hasOwnProperty('conferenceCall');\n"
2775        "if (!hasOwnProperty) {\n"
2776        "    flags |= 8;\n"
2777        "}\n"
2778        "return flags;\n",
2779        0},
2780       {"var data = {x:23, y:34};\n"
2781        " var result = 0;\n"
2782        "var o = {};\n"
2783        "var arr = [o];\n"
2784        "for (arr[0].p in data)\n"       // This is to test if value is loaded
2785        "  result += data[arr[0].p];\n"  // back from accumulator before storing
2786        "return result;\n",              // named properties.
2787        57},
2788       {"var data = {x:23, y:34};\n"
2789        "var result = 0;\n"
2790        "var o = {};\n"
2791        "var i = 0;\n"
2792        "for (o[i++] in data)\n"       // This is to test if value is loaded
2793        "  result += data[o[i-1]];\n"  // back from accumulator before
2794        "return result;\n",            // storing keyed properties.
2795        57}};
2796 
2797   // Two passes are made for this test. On the first, 8-bit register
2798   // operands are employed, and on the 16-bit register operands are
2799   // used.
2800   for (int pass = 0; pass < 2; pass++) {
2801     HandleAndZoneScope handles;
2802     std::ostringstream wide_os;
2803     if (pass == 1) {
2804       for (int i = 0; i < 200; i++) {
2805         wide_os << "var local" << i << " = 0;\n";
2806       }
2807     }
2808 
2809     for (size_t i = 0; i < arraysize(for_in_samples); i++) {
2810       std::ostringstream body_os;
2811       body_os << wide_os.str() << for_in_samples[i].first;
2812       std::string body(body_os.str());
2813       std::string function = InterpreterTester::SourceForBody(body.c_str());
2814       InterpreterTester tester(handles.main_isolate(), function.c_str());
2815       auto callable = tester.GetCallable<>();
2816       Handle<Object> return_val = callable().ToHandleChecked();
2817       CHECK_EQ(Handle<Smi>::cast(return_val)->value(),
2818                for_in_samples[i].second);
2819     }
2820   }
2821 }
2822 
2823 
TEST(InterpreterForOf)2824 TEST(InterpreterForOf) {
2825   HandleAndZoneScope handles;
2826   i::Isolate* isolate = handles.main_isolate();
2827   i::Factory* factory = isolate->factory();
2828 
2829   std::pair<const char*, Handle<Object>> for_of[] = {
2830       {"function f() {\n"
2831        "  var r = 0;\n"
2832        "  for (var a of [0,6,7,9]) { r += a; }\n"
2833        "  return r;\n"
2834        "}",
2835        handle(Smi::FromInt(22), isolate)},
2836       {"function f() {\n"
2837        "  var r = '';\n"
2838        "  for (var a of 'foobar') { r = a + r; }\n"
2839        "  return r;\n"
2840        "}",
2841        factory->NewStringFromStaticChars("raboof")},
2842       {"function f() {\n"
2843        "  var a = [1, 2, 3];\n"
2844        "  a.name = 4;\n"
2845        "  var r = 0;\n"
2846        "  for (var x of a) { r += x; }\n"
2847        "  return r;\n"
2848        "}",
2849        handle(Smi::FromInt(6), isolate)},
2850       {"function f() {\n"
2851        "  var r = '';\n"
2852        "  var data = [1, 2, 3]; \n"
2853        "  for (a of data) { delete data[0]; r += a; } return r; }",
2854        factory->NewStringFromStaticChars("123")},
2855       {"function f() {\n"
2856        "  var r = '';\n"
2857        "  var data = [1, 2, 3]; \n"
2858        "  for (a of data) { delete data[2]; r += a; } return r; }",
2859        factory->NewStringFromStaticChars("12undefined")},
2860       {"function f() {\n"
2861        "  var r = '';\n"
2862        "  var data = [1, 2, 3]; \n"
2863        "  for (a of data) { delete data; r += a; } return r; }",
2864        factory->NewStringFromStaticChars("123")},
2865       {"function f() {\n"
2866        "  var r = '';\n"
2867        "  var input = 'foobar';\n"
2868        "  for (var a of input) {\n"
2869        "    if (a == 'b') break;\n"
2870        "    r += a;\n"
2871        "  }\n"
2872        "  return r;\n"
2873        "}",
2874        factory->NewStringFromStaticChars("foo")},
2875       {"function f() {\n"
2876        "  var r = '';\n"
2877        "  var input = 'foobar';\n"
2878        "  for (var a of input) {\n"
2879        "    if (a == 'b') continue;\n"
2880        "    r += a;\n"
2881        "  }\n"
2882        "  return r;\n"
2883        "}",
2884        factory->NewStringFromStaticChars("fooar")},
2885       {"function f() {\n"
2886        "  var r = '';\n"
2887        "  var data = [1, 2, 3, 4]; \n"
2888        "  for (a of data) { data[2] = 567; r += a; }\n"
2889        "  return r;\n"
2890        "}",
2891        factory->NewStringFromStaticChars("125674")},
2892       {"function f() {\n"
2893        "  var r = '';\n"
2894        "  var data = [1, 2, 3, 4]; \n"
2895        "  for (a of data) { data[4] = 567; r += a; }\n"
2896        "  return r;\n"
2897        "}",
2898        factory->NewStringFromStaticChars("1234567")},
2899       {"function f() {\n"
2900        "  var r = '';\n"
2901        "  var data = [1, 2, 3, 4]; \n"
2902        "  for (a of data) { data[5] = 567; r += a; }\n"
2903        "  return r;\n"
2904        "}",
2905        factory->NewStringFromStaticChars("1234undefined567")},
2906       {"function f() {\n"
2907        "  var r = '';\n"
2908        "  var obj = new Object();\n"
2909        "  obj[Symbol.iterator] = function() { return {\n"
2910        "    index: 3,\n"
2911        "    data: ['a', 'b', 'c', 'd'],"
2912        "    next: function() {"
2913        "      return {"
2914        "        done: this.index == -1,\n"
2915        "        value: this.index < 0 ? undefined : this.data[this.index--]\n"
2916        "      }\n"
2917        "    }\n"
2918        "    }}\n"
2919        "  for (a of obj) { r += a }\n"
2920        "  return r;\n"
2921        "}",
2922        factory->NewStringFromStaticChars("dcba")},
2923   };
2924 
2925   for (size_t i = 0; i < arraysize(for_of); i++) {
2926     InterpreterTester tester(handles.main_isolate(), for_of[i].first);
2927     auto callable = tester.GetCallable<>();
2928     Handle<Object> return_val = callable().ToHandleChecked();
2929     CHECK(return_val->SameValue(*for_of[i].second));
2930   }
2931 }
2932 
2933 
TEST(InterpreterSwitch)2934 TEST(InterpreterSwitch) {
2935   HandleAndZoneScope handles;
2936   i::Isolate* isolate = handles.main_isolate();
2937   i::Factory* factory = isolate->factory();
2938 
2939   std::pair<const char*, Handle<Object>> switch_ops[] = {
2940       std::make_pair("var a = 1;\n"
2941                      "switch(a) {\n"
2942                      " case 1: return 2;\n"
2943                      " case 2: return 3;\n"
2944                      "}\n",
2945                      handle(Smi::FromInt(2), isolate)),
2946       std::make_pair("var a = 1;\n"
2947                      "switch(a) {\n"
2948                      " case 2: a = 2; break;\n"
2949                      " case 1: a = 3; break;\n"
2950                      "}\n"
2951                      "return a;",
2952                      handle(Smi::FromInt(3), isolate)),
2953       std::make_pair("var a = 1;\n"
2954                      "switch(a) {\n"
2955                      " case 1: a = 2; // fall-through\n"
2956                      " case 2: a = 3; break;\n"
2957                      "}\n"
2958                      "return a;",
2959                      handle(Smi::FromInt(3), isolate)),
2960       std::make_pair("var a = 100;\n"
2961                      "switch(a) {\n"
2962                      " case 1: return 100;\n"
2963                      " case 2: return 200;\n"
2964                      "}\n"
2965                      "return undefined;",
2966                      factory->undefined_value()),
2967       std::make_pair("var a = 100;\n"
2968                      "switch(a) {\n"
2969                      " case 1: return 100;\n"
2970                      " case 2: return 200;\n"
2971                      " default: return 300;\n"
2972                      "}\n"
2973                      "return undefined;",
2974                      handle(Smi::FromInt(300), isolate)),
2975       std::make_pair("var a = 100;\n"
2976                      "switch(typeof(a)) {\n"
2977                      " case 'string': return 1;\n"
2978                      " case 'number': return 2;\n"
2979                      " default: return 3;\n"
2980                      "}\n",
2981                      handle(Smi::FromInt(2), isolate)),
2982       std::make_pair("var a = 100;\n"
2983                      "switch(a) {\n"
2984                      " case a += 20: return 1;\n"
2985                      " case a -= 10: return 2;\n"
2986                      " case a -= 10: return 3;\n"
2987                      " default: return 3;\n"
2988                      "}\n",
2989                      handle(Smi::FromInt(3), isolate)),
2990       std::make_pair("var a = 1;\n"
2991                      "switch(a) {\n"
2992                      " case 1: \n"
2993                      "   switch(a + 1) {\n"
2994                      "      case 2 : a += 1; break;\n"
2995                      "      default : a += 2; break;\n"
2996                      "   }  // fall-through\n"
2997                      " case 2: a += 3;\n"
2998                      "}\n"
2999                      "return a;",
3000                      handle(Smi::FromInt(5), isolate)),
3001   };
3002 
3003   for (size_t i = 0; i < arraysize(switch_ops); i++) {
3004     std::string source(InterpreterTester::SourceForBody(switch_ops[i].first));
3005     InterpreterTester tester(handles.main_isolate(), source.c_str());
3006     auto callable = tester.GetCallable<>();
3007 
3008     Handle<i::Object> return_value = callable().ToHandleChecked();
3009     CHECK(return_value->SameValue(*switch_ops[i].second));
3010   }
3011 }
3012 
3013 
TEST(InterpreterSloppyThis)3014 TEST(InterpreterSloppyThis) {
3015   HandleAndZoneScope handles;
3016   i::Isolate* isolate = handles.main_isolate();
3017   i::Factory* factory = isolate->factory();
3018 
3019   std::pair<const char*, Handle<Object>> sloppy_this[] = {
3020       std::make_pair("var global_val = 100;\n"
3021                      "function f() { return this.global_val; }\n",
3022                      handle(Smi::FromInt(100), isolate)),
3023       std::make_pair("var global_val = 110;\n"
3024                      "function g() { return this.global_val; };"
3025                      "function f() { return g(); }\n",
3026                      handle(Smi::FromInt(110), isolate)),
3027       std::make_pair("var global_val = 110;\n"
3028                      "function g() { return this.global_val };"
3029                      "function f() { 'use strict'; return g(); }\n",
3030                      handle(Smi::FromInt(110), isolate)),
3031       std::make_pair("function f() { 'use strict'; return this; }\n",
3032                      factory->undefined_value()),
3033       std::make_pair("function g() { 'use strict'; return this; };"
3034                      "function f() { return g(); }\n",
3035                      factory->undefined_value()),
3036   };
3037 
3038   for (size_t i = 0; i < arraysize(sloppy_this); i++) {
3039     InterpreterTester tester(handles.main_isolate(), sloppy_this[i].first);
3040     auto callable = tester.GetCallable<>();
3041 
3042     Handle<i::Object> return_value = callable().ToHandleChecked();
3043     CHECK(return_value->SameValue(*sloppy_this[i].second));
3044   }
3045 }
3046 
3047 
TEST(InterpreterThisFunction)3048 TEST(InterpreterThisFunction) {
3049   HandleAndZoneScope handles;
3050   i::Isolate* isolate = handles.main_isolate();
3051   i::Factory* factory = isolate->factory();
3052 
3053   InterpreterTester tester(handles.main_isolate(),
3054                            "var f;\n f = function f() { return f.name; }");
3055   auto callable = tester.GetCallable<>();
3056 
3057   Handle<i::Object> return_value = callable().ToHandleChecked();
3058   CHECK(return_value->SameValue(*factory->NewStringFromStaticChars("f")));
3059 }
3060 
3061 
TEST(InterpreterNewTarget)3062 TEST(InterpreterNewTarget) {
3063   HandleAndZoneScope handles;
3064   i::Isolate* isolate = handles.main_isolate();
3065   i::Factory* factory = isolate->factory();
3066 
3067   // TODO(rmcilroy): Add tests that we get the original constructor for
3068   // superclass constructors once we have class support.
3069   InterpreterTester tester(handles.main_isolate(),
3070                            "function f() { this.a = new.target; }");
3071   auto callable = tester.GetCallable<>();
3072   callable().ToHandleChecked();
3073 
3074   Handle<Object> new_target_name = v8::Utils::OpenHandle(
3075       *CompileRun("(function() { return (new f()).a.name; })();"));
3076   CHECK(new_target_name->SameValue(*factory->NewStringFromStaticChars("f")));
3077 }
3078 
3079 
TEST(InterpreterAssignmentInExpressions)3080 TEST(InterpreterAssignmentInExpressions) {
3081   HandleAndZoneScope handles;
3082 
3083   std::pair<const char*, int> samples[] = {
3084       {"function f() {\n"
3085        "  var x = 7;\n"
3086        "  var y = x + (x = 1) + (x = 2);\n"
3087        "  return y;\n"
3088        "}",
3089        10},
3090       {"function f() {\n"
3091        "  var x = 7;\n"
3092        "  var y = x + (x = 1) + (x = 2);\n"
3093        "  return x;\n"
3094        "}",
3095        2},
3096       {"function f() {\n"
3097        "  var x = 55;\n"
3098        "  x = x + (x = 100) + (x = 101);\n"
3099        "  return x;\n"
3100        "}",
3101        256},
3102       {"function f() {\n"
3103        "  var x = 7;\n"
3104        "  return ++x + x + x++;\n"
3105        "}",
3106        24},
3107       {"function f() {\n"
3108        "  var x = 7;\n"
3109        "  var y = 1 + ++x + x + x++;\n"
3110        "  return x;\n"
3111        "}",
3112        9},
3113       {"function f() {\n"
3114        "  var x = 7;\n"
3115        "  var y = ++x + x + x++;\n"
3116        "  return x;\n"
3117        "}",
3118        9},
3119       {"function f() {\n"
3120        "  var x = 7, y = 100, z = 1000;\n"
3121        "  return x + (x += 3) + y + (y *= 10) + (z *= 7) + z;\n"
3122        "}",
3123        15117},
3124       {"function f() {\n"
3125        "  var inner = function (x) { return x + (x = 2) + (x = 4) + x; };\n"
3126        "  return inner(1);\n"
3127        "}",
3128        11},
3129       {"function f() {\n"
3130        "  var x = 1, y = 2;\n"
3131        "  x = x + (x = 3) + y + (y = 4), y = y + (y = 5) + y + x;\n"
3132        "  return x + y;\n"
3133        "}",
3134        10 + 24},
3135       {"function f() {\n"
3136        "  var x = 0;\n"
3137        "  var y = x | (x = 1) | (x = 2);\n"
3138        "  return x;\n"
3139        "}",
3140        2},
3141       {"function f() {\n"
3142        "  var x = 0;\n"
3143        "  var y = x || (x = 1);\n"
3144        "  return x;\n"
3145        "}",
3146        1},
3147       {"function f() {\n"
3148        "  var x = 1;\n"
3149        "  var y = x && (x = 2) && (x = 3);\n"
3150        "  return x;\n"
3151        "}",
3152        3},
3153       {"function f() {\n"
3154        "  var x = 1;\n"
3155        "  var y = x || (x = 2);\n"
3156        "  return x;\n"
3157        "}",
3158        1},
3159       {"function f() {\n"
3160        "  var x = 1;\n"
3161        "  x = (x << (x = 3)) | (x = 16);\n"
3162        "  return x;\n"
3163        "}",
3164        24},
3165       {"function f() {\n"
3166        "  var r = 7;\n"
3167        "  var s = 11;\n"
3168        "  var t = 13;\n"
3169        "  var u = r + s + t + (r = 10) + (s = 20) +"
3170        "          (t = (r + s)) + r + s + t;\n"
3171        "  return r + s + t + u;\n"
3172        "}",
3173        211},
3174       {"function f() {\n"
3175        "  var r = 7;\n"
3176        "  var s = 11;\n"
3177        "  var t = 13;\n"
3178        "  return r > (3 * s * (s = 1)) ? (t + (t += 1)) : (r + (r = 4));\n"
3179        "}",
3180        11},
3181       {"function f() {\n"
3182        "  var r = 7;\n"
3183        "  var s = 11;\n"
3184        "  var t = 13;\n"
3185        "  return r > (3 * s * (s = 0)) ? (t + (t += 1)) : (r + (r = 4));\n"
3186        "}",
3187        27},
3188       {"function f() {\n"
3189        "  var r = 7;\n"
3190        "  var s = 11;\n"
3191        "  var t = 13;\n"
3192        "  return (r + (r = 5)) > s ? r : t;\n"
3193        "}",
3194        5},
3195       {"function f(a) {\n"
3196        "  return a + (arguments[0] = 10);\n"
3197        "}",
3198        50},
3199       {"function f(a) {\n"
3200        "  return a + (arguments[0] = 10) + a;\n"
3201        "}",
3202        60},
3203       {"function f(a) {\n"
3204        "  return a + (arguments[0] = 10) + arguments[0];\n"
3205        "}",
3206        60},
3207   };
3208 
3209   const int arg_value = 40;
3210   for (size_t i = 0; i < arraysize(samples); i++) {
3211     InterpreterTester tester(handles.main_isolate(), samples[i].first);
3212     auto callable = tester.GetCallable<Handle<Object>>();
3213     Handle<Object> return_val =
3214         callable(handle(Smi::FromInt(arg_value), handles.main_isolate()))
3215             .ToHandleChecked();
3216     CHECK_EQ(Handle<Smi>::cast(return_val)->value(), samples[i].second);
3217   }
3218 }
3219 
3220 
TEST(InterpreterToName)3221 TEST(InterpreterToName) {
3222   HandleAndZoneScope handles;
3223   i::Isolate* isolate = handles.main_isolate();
3224   i::Factory* factory = isolate->factory();
3225 
3226   std::pair<const char*, Handle<Object>> to_name_tests[] = {
3227       {"var a = 'val'; var obj = {[a] : 10}; return obj.val;",
3228        factory->NewNumberFromInt(10)},
3229       {"var a = 20; var obj = {[a] : 10}; return obj['20'];",
3230        factory->NewNumberFromInt(10)},
3231       {"var a = 20; var obj = {[a] : 10}; return obj[20];",
3232        factory->NewNumberFromInt(10)},
3233       {"var a = {val:23}; var obj = {[a] : 10}; return obj[a];",
3234        factory->NewNumberFromInt(10)},
3235       {"var a = {val:23}; var obj = {[a] : 10};\n"
3236        "return obj['[object Object]'];",
3237        factory->NewNumberFromInt(10)},
3238       {"var a = {toString : function() { return 'x'}};\n"
3239        "var obj = {[a] : 10};\n"
3240        "return obj.x;",
3241        factory->NewNumberFromInt(10)},
3242       {"var a = {valueOf : function() { return 'x'}};\n"
3243        "var obj = {[a] : 10};\n"
3244        "return obj.x;",
3245        factory->undefined_value()},
3246       {"var a = {[Symbol.toPrimitive] : function() { return 'x'}};\n"
3247        "var obj = {[a] : 10};\n"
3248        "return obj.x;",
3249        factory->NewNumberFromInt(10)},
3250   };
3251 
3252   for (size_t i = 0; i < arraysize(to_name_tests); i++) {
3253     std::string source(
3254         InterpreterTester::SourceForBody(to_name_tests[i].first));
3255     InterpreterTester tester(handles.main_isolate(), source.c_str());
3256     auto callable = tester.GetCallable<>();
3257 
3258     Handle<i::Object> return_value = callable().ToHandleChecked();
3259     CHECK(return_value->SameValue(*to_name_tests[i].second));
3260   }
3261 }
3262 
3263 
TEST(TemporaryRegisterAllocation)3264 TEST(TemporaryRegisterAllocation) {
3265   HandleAndZoneScope handles;
3266   i::Isolate* isolate = handles.main_isolate();
3267   i::Factory* factory = isolate->factory();
3268 
3269   std::pair<const char*, Handle<Object>> reg_tests[] = {
3270       {"function add(a, b, c) {"
3271        "   return a + b + c;"
3272        "}"
3273        "function f() {"
3274        "  var a = 10, b = 10;"
3275        "   return add(a, b++, b);"
3276        "}",
3277        factory->NewNumberFromInt(31)},
3278       {"function add(a, b, c, d) {"
3279        "  return a + b + c + d;"
3280        "}"
3281        "function f() {"
3282        "  var x = 10, y = 20, z = 30;"
3283        "  return x + add(x, (y= x++), x, z);"
3284        "}",
3285        factory->NewNumberFromInt(71)},
3286   };
3287 
3288   for (size_t i = 0; i < arraysize(reg_tests); i++) {
3289     InterpreterTester tester(handles.main_isolate(), reg_tests[i].first);
3290     auto callable = tester.GetCallable<>();
3291 
3292     Handle<i::Object> return_value = callable().ToHandleChecked();
3293     CHECK(return_value->SameValue(*reg_tests[i].second));
3294   }
3295 }
3296 
3297 
TEST(InterpreterLookupSlot)3298 TEST(InterpreterLookupSlot) {
3299   HandleAndZoneScope handles;
3300   i::Isolate* isolate = handles.main_isolate();
3301   i::Factory* factory = isolate->factory();
3302 
3303   // TODO(mythria): Add more tests when we have support for eval/with.
3304   const char* function_prologue = "var f;"
3305                                   "var x = 1;"
3306                                   "function f1() {"
3307                                   "  eval(\"function t() {";
3308   const char* function_epilogue = "        }; f = t;\");"
3309                                   "}"
3310                                   "f1();";
3311 
3312 
3313   std::pair<const char*, Handle<Object>> lookup_slot[] = {
3314       {"return x;", handle(Smi::FromInt(1), isolate)},
3315       {"return typeof x;", factory->NewStringFromStaticChars("number")},
3316       {"return typeof dummy;", factory->NewStringFromStaticChars("undefined")},
3317       {"x = 10; return x;", handle(Smi::FromInt(10), isolate)},
3318       {"'use strict'; x = 20; return x;", handle(Smi::FromInt(20), isolate)},
3319   };
3320 
3321   for (size_t i = 0; i < arraysize(lookup_slot); i++) {
3322     std::string script = std::string(function_prologue) +
3323                          std::string(lookup_slot[i].first) +
3324                          std::string(function_epilogue);
3325 
3326     InterpreterTester tester(handles.main_isolate(), script.c_str(), "t");
3327     auto callable = tester.GetCallable<>();
3328 
3329     Handle<i::Object> return_value = callable().ToHandleChecked();
3330     CHECK(return_value->SameValue(*lookup_slot[i].second));
3331   }
3332 }
3333 
3334 
TEST(InterpreterCallLookupSlot)3335 TEST(InterpreterCallLookupSlot) {
3336   HandleAndZoneScope handles;
3337   i::Isolate* isolate = handles.main_isolate();
3338 
3339   std::pair<const char*, Handle<Object>> call_lookup[] = {
3340       {"g = function(){ return 2 }; eval(''); return g();",
3341        handle(Smi::FromInt(2), isolate)},
3342       {"g = function(){ return 2 }; eval('g = function() {return 3}');\n"
3343        "return g();",
3344        handle(Smi::FromInt(3), isolate)},
3345       {"g = { x: function(){ return this.y }, y: 20 };\n"
3346        "eval('g = { x: g.x, y: 30 }');\n"
3347        "return g.x();",
3348        handle(Smi::FromInt(30), isolate)},
3349   };
3350 
3351   for (size_t i = 0; i < arraysize(call_lookup); i++) {
3352     std::string source(InterpreterTester::SourceForBody(call_lookup[i].first));
3353     InterpreterTester tester(handles.main_isolate(), source.c_str());
3354     auto callable = tester.GetCallable<>();
3355 
3356     Handle<i::Object> return_value = callable().ToHandleChecked();
3357     CHECK(return_value->SameValue(*call_lookup[i].second));
3358   }
3359 }
3360 
3361 
TEST(InterpreterLookupSlotWide)3362 TEST(InterpreterLookupSlotWide) {
3363   HandleAndZoneScope handles;
3364   i::Isolate* isolate = handles.main_isolate();
3365   i::Factory* factory = isolate->factory();
3366 
3367   const char* function_prologue =
3368       "var f;"
3369       "var x = 1;"
3370       "function f1() {"
3371       "  eval(\"function t() {";
3372   const char* function_epilogue =
3373       "        }; f = t;\");"
3374       "}"
3375       "f1();";
3376   std::ostringstream str;
3377   str << "var y = 2.3;";
3378   for (int i = 1; i < 256; i++) {
3379     str << "y = " << 2.3 + i << ";";
3380   }
3381   std::string init_function_body = str.str();
3382 
3383   std::pair<std::string, Handle<Object>> lookup_slot[] = {
3384       {init_function_body + "return x;", handle(Smi::FromInt(1), isolate)},
3385       {init_function_body + "return typeof x;",
3386        factory->NewStringFromStaticChars("number")},
3387       {init_function_body + "return x = 10;",
3388        handle(Smi::FromInt(10), isolate)},
3389       {"'use strict';" + init_function_body + "x = 20; return x;",
3390        handle(Smi::FromInt(20), isolate)},
3391   };
3392 
3393   for (size_t i = 0; i < arraysize(lookup_slot); i++) {
3394     std::string script = std::string(function_prologue) + lookup_slot[i].first +
3395                          std::string(function_epilogue);
3396 
3397     InterpreterTester tester(handles.main_isolate(), script.c_str(), "t");
3398     auto callable = tester.GetCallable<>();
3399 
3400     Handle<i::Object> return_value = callable().ToHandleChecked();
3401     CHECK(return_value->SameValue(*lookup_slot[i].second));
3402   }
3403 }
3404 
3405 
TEST(InterpreterDeleteLookupSlot)3406 TEST(InterpreterDeleteLookupSlot) {
3407   HandleAndZoneScope handles;
3408   i::Isolate* isolate = handles.main_isolate();
3409   i::Factory* factory = isolate->factory();
3410 
3411   // TODO(mythria): Add more tests when we have support for eval/with.
3412   const char* function_prologue = "var f;"
3413                                   "var x = 1;"
3414                                   "y = 10;"
3415                                   "var obj = {val:10};"
3416                                   "var z = 30;"
3417                                   "function f1() {"
3418                                   "  var z = 20;"
3419                                   "  eval(\"function t() {";
3420   const char* function_epilogue = "        }; f = t;\");"
3421                                   "}"
3422                                   "f1();";
3423 
3424 
3425   std::pair<const char*, Handle<Object>> delete_lookup_slot[] = {
3426       {"return delete x;", factory->false_value()},
3427       {"return delete y;", factory->true_value()},
3428       {"return delete z;", factory->false_value()},
3429       {"return delete obj.val;", factory->true_value()},
3430       {"'use strict'; return delete obj.val;", factory->true_value()},
3431   };
3432 
3433   for (size_t i = 0; i < arraysize(delete_lookup_slot); i++) {
3434     std::string script = std::string(function_prologue) +
3435                          std::string(delete_lookup_slot[i].first) +
3436                          std::string(function_epilogue);
3437 
3438     InterpreterTester tester(handles.main_isolate(), script.c_str(), "t");
3439     auto callable = tester.GetCallable<>();
3440 
3441     Handle<i::Object> return_value = callable().ToHandleChecked();
3442     CHECK(return_value->SameValue(*delete_lookup_slot[i].second));
3443   }
3444 }
3445 
3446 
TEST(JumpWithConstantsAndWideConstants)3447 TEST(JumpWithConstantsAndWideConstants) {
3448   HandleAndZoneScope handles;
3449   const int kStep = 13;
3450   for (int constants = 11; constants < 256 + 3 * kStep; constants += kStep) {
3451     auto isolate = handles.main_isolate();
3452     auto factory = isolate->factory();
3453     std::ostringstream filler_os;
3454     // Generate a string that consumes constant pool entries and
3455     // spread out branch distances in script below.
3456     for (int i = 0; i < constants; i++) {
3457       filler_os << "var x_ = 'x_" << i << "';\n";
3458     }
3459     std::string filler(filler_os.str());
3460     std::ostringstream script_os;
3461     script_os << "function " << InterpreterTester::function_name() << "(a) {\n";
3462     script_os << "  " << filler;
3463     script_os << "  for (var i = a; i < 2; i++) {\n";
3464     script_os << "  " << filler;
3465     script_os << "    if (i == 0) { " << filler << "i = 10; continue; }\n";
3466     script_os << "    else if (i == a) { " << filler << "i = 12; break; }\n";
3467     script_os << "    else { " << filler << " }\n";
3468     script_os << "  }\n";
3469     script_os << "  return i;\n";
3470     script_os << "}\n";
3471     std::string script(script_os.str());
3472     for (int a = 0; a < 3; a++) {
3473       InterpreterTester tester(handles.main_isolate(), script.c_str());
3474       auto callable = tester.GetCallable<Handle<Object>>();
3475       Handle<Object> argument = factory->NewNumberFromInt(a);
3476       Handle<Object> return_val = callable(argument).ToHandleChecked();
3477       static const int results[] = {11, 12, 2};
3478       CHECK_EQ(Handle<Smi>::cast(return_val)->value(), results[a]);
3479     }
3480   }
3481 }
3482 
3483 
TEST(InterpreterEval)3484 TEST(InterpreterEval) {
3485   HandleAndZoneScope handles;
3486   i::Isolate* isolate = handles.main_isolate();
3487   i::Factory* factory = isolate->factory();
3488 
3489   std::pair<const char*, Handle<Object>> eval[] = {
3490       {"return eval('1;');", handle(Smi::FromInt(1), isolate)},
3491       {"return eval('100 * 20;');", handle(Smi::FromInt(2000), isolate)},
3492       {"var x = 10; return eval('x + 20;');",
3493        handle(Smi::FromInt(30), isolate)},
3494       {"var x = 10; eval('x = 33;'); return x;",
3495        handle(Smi::FromInt(33), isolate)},
3496       {"'use strict'; var x = 20; var z = 0;\n"
3497        "eval('var x = 33; z = x;'); return x + z;",
3498        handle(Smi::FromInt(53), isolate)},
3499       {"eval('var x = 33;'); eval('var y = x + 20'); return x + y;",
3500        handle(Smi::FromInt(86), isolate)},
3501       {"var x = 1; eval('for(i = 0; i < 10; i++) x = x + 1;'); return x",
3502        handle(Smi::FromInt(11), isolate)},
3503       {"var x = 10; eval('var x = 20;'); return x;",
3504        handle(Smi::FromInt(20), isolate)},
3505       {"var x = 1; eval('\"use strict\"; var x = 2;'); return x;",
3506        handle(Smi::FromInt(1), isolate)},
3507       {"'use strict'; var x = 1; eval('var x = 2;'); return x;",
3508        handle(Smi::FromInt(1), isolate)},
3509       {"var x = 10; eval('x + 20;'); return typeof x;",
3510        factory->NewStringFromStaticChars("number")},
3511       {"eval('var y = 10;'); return typeof unallocated;",
3512        factory->NewStringFromStaticChars("undefined")},
3513       {"'use strict'; eval('var y = 10;'); return typeof unallocated;",
3514        factory->NewStringFromStaticChars("undefined")},
3515       {"eval('var x = 10;'); return typeof x;",
3516        factory->NewStringFromStaticChars("number")},
3517       {"var x = {}; eval('var x = 10;'); return typeof x;",
3518        factory->NewStringFromStaticChars("number")},
3519       {"'use strict'; var x = {}; eval('var x = 10;'); return typeof x;",
3520        factory->NewStringFromStaticChars("object")},
3521   };
3522 
3523   for (size_t i = 0; i < arraysize(eval); i++) {
3524     std::string source(InterpreterTester::SourceForBody(eval[i].first));
3525     InterpreterTester tester(handles.main_isolate(), source.c_str());
3526     auto callable = tester.GetCallable<>();
3527     Handle<i::Object> return_value = callable().ToHandleChecked();
3528     CHECK(return_value->SameValue(*eval[i].second));
3529   }
3530 }
3531 
3532 
TEST(InterpreterEvalParams)3533 TEST(InterpreterEvalParams) {
3534   HandleAndZoneScope handles;
3535   i::Isolate* isolate = handles.main_isolate();
3536 
3537   std::pair<const char*, Handle<Object>> eval_params[] = {
3538       {"var x = 10; return eval('x + p1;');",
3539        handle(Smi::FromInt(30), isolate)},
3540       {"var x = 10; eval('p1 = x;'); return p1;",
3541        handle(Smi::FromInt(10), isolate)},
3542       {"var a = 10;"
3543        "function inner() { return eval('a + p1;');}"
3544        "return inner();",
3545        handle(Smi::FromInt(30), isolate)},
3546   };
3547 
3548   for (size_t i = 0; i < arraysize(eval_params); i++) {
3549     std::string source = "function " + InterpreterTester::function_name() +
3550                          "(p1) {" + eval_params[i].first + "}";
3551     InterpreterTester tester(handles.main_isolate(), source.c_str());
3552     auto callable = tester.GetCallable<Handle<Object>>();
3553 
3554     Handle<i::Object> return_value =
3555         callable(handle(Smi::FromInt(20), isolate)).ToHandleChecked();
3556     CHECK(return_value->SameValue(*eval_params[i].second));
3557   }
3558 }
3559 
3560 
TEST(InterpreterEvalGlobal)3561 TEST(InterpreterEvalGlobal) {
3562   HandleAndZoneScope handles;
3563   i::Isolate* isolate = handles.main_isolate();
3564   i::Factory* factory = isolate->factory();
3565 
3566   std::pair<const char*, Handle<Object>> eval_global[] = {
3567       {"function add_global() { eval('function test() { z = 33; }; test()'); };"
3568        "function f() { add_global(); return z; }; f();",
3569        handle(Smi::FromInt(33), isolate)},
3570       {"function add_global() {\n"
3571        " eval('\"use strict\"; function test() { y = 33; };"
3572        "      try { test() } catch(e) {}');\n"
3573        "}\n"
3574        "function f() { add_global(); return typeof y; } f();",
3575        factory->NewStringFromStaticChars("undefined")},
3576   };
3577 
3578   for (size_t i = 0; i < arraysize(eval_global); i++) {
3579     InterpreterTester tester(handles.main_isolate(), eval_global[i].first,
3580                              "test");
3581     auto callable = tester.GetCallable<>();
3582 
3583     Handle<i::Object> return_value = callable().ToHandleChecked();
3584     CHECK(return_value->SameValue(*eval_global[i].second));
3585   }
3586 }
3587 
3588 
TEST(InterpreterEvalVariableDecl)3589 TEST(InterpreterEvalVariableDecl) {
3590   HandleAndZoneScope handles;
3591   i::Isolate* isolate = handles.main_isolate();
3592   i::Factory* factory = isolate->factory();
3593 
3594   std::pair<const char*, Handle<Object>> eval_global[] = {
3595       {"function f() { eval('var x = 10; x++;'); return x; }",
3596        handle(Smi::FromInt(11), isolate)},
3597       {"function f() { var x = 20; eval('var x = 10; x++;'); return x; }",
3598        handle(Smi::FromInt(11), isolate)},
3599       {"function f() {"
3600        " var x = 20;"
3601        " eval('\"use strict\"; var x = 10; x++;');"
3602        " return x; }",
3603        handle(Smi::FromInt(20), isolate)},
3604       {"function f() {"
3605        " var y = 30;"
3606        " eval('var x = {1:20}; x[2]=y;');"
3607        " return x[2]; }",
3608        handle(Smi::FromInt(30), isolate)},
3609       {"function f() {"
3610        " eval('var x = {name:\"test\"};');"
3611        " return x.name; }",
3612        factory->NewStringFromStaticChars("test")},
3613       {"function f() {"
3614        "  eval('var x = [{name:\"test\"}, {type:\"cc\"}];');"
3615        "  return x[1].type+x[0].name; }",
3616        factory->NewStringFromStaticChars("cctest")},
3617       {"function f() {\n"
3618        " var x = 3;\n"
3619        " var get_eval_x;\n"
3620        " eval('\"use strict\"; "
3621        "      var x = 20; "
3622        "      get_eval_x = function func() {return x;};');\n"
3623        " return get_eval_x() + x;\n"
3624        "}",
3625        handle(Smi::FromInt(23), isolate)},
3626       // TODO(mythria): Add tests with const declarations.
3627   };
3628 
3629   for (size_t i = 0; i < arraysize(eval_global); i++) {
3630     InterpreterTester tester(handles.main_isolate(), eval_global[i].first, "*");
3631     auto callable = tester.GetCallable<>();
3632 
3633     Handle<i::Object> return_value = callable().ToHandleChecked();
3634     CHECK(return_value->SameValue(*eval_global[i].second));
3635   }
3636 }
3637 
3638 
TEST(InterpreterEvalFunctionDecl)3639 TEST(InterpreterEvalFunctionDecl) {
3640   HandleAndZoneScope handles;
3641   i::Isolate* isolate = handles.main_isolate();
3642 
3643   std::pair<const char*, Handle<Object>> eval_func_decl[] = {
3644       {"function f() {\n"
3645        " var x = 3;\n"
3646        " eval('var x = 20;"
3647        "       function get_x() {return x;};');\n"
3648        " return get_x() + x;\n"
3649        "}",
3650        handle(Smi::FromInt(40), isolate)},
3651   };
3652 
3653   for (size_t i = 0; i < arraysize(eval_func_decl); i++) {
3654     InterpreterTester tester(handles.main_isolate(), eval_func_decl[i].first,
3655                              "*");
3656     auto callable = tester.GetCallable<>();
3657 
3658     Handle<i::Object> return_value = callable().ToHandleChecked();
3659     CHECK(return_value->SameValue(*eval_func_decl[i].second));
3660   }
3661 }
3662 
TEST(InterpreterWideRegisterArithmetic)3663 TEST(InterpreterWideRegisterArithmetic) {
3664   HandleAndZoneScope handles;
3665   i::Isolate* isolate = handles.main_isolate();
3666 
3667   static const size_t kMaxRegisterForTest = 150;
3668   std::ostringstream os;
3669   os << "function " << InterpreterTester::function_name() << "(arg) {\n";
3670   os << "  var retval = -77;\n";
3671   for (size_t i = 0; i < kMaxRegisterForTest; i++) {
3672     os << "  var x" << i << " = " << i << ";\n";
3673   }
3674   for (size_t i = 0; i < kMaxRegisterForTest / 2; i++) {
3675     size_t j = kMaxRegisterForTest - i - 1;
3676     os << "  var tmp = x" << j << ";\n";
3677     os << "  var x" << j << " = x" << i << ";\n";
3678     os << "  var x" << i << " = tmp;\n";
3679   }
3680   for (size_t i = 0; i < kMaxRegisterForTest / 2; i++) {
3681     size_t j = kMaxRegisterForTest - i - 1;
3682     os << "  var tmp = x" << j << ";\n";
3683     os << "  var x" << j << " = x" << i << ";\n";
3684     os << "  var x" << i << " = tmp;\n";
3685   }
3686   for (size_t i = 0; i < kMaxRegisterForTest; i++) {
3687     os << "  if (arg == " << i << ") {\n"  //
3688        << "    retval = x" << i << ";\n"   //
3689        << "  }\n";                         //
3690   }
3691   os << "  return retval;\n";
3692   os << "}\n";
3693 
3694   std::string source = os.str();
3695   InterpreterTester tester(handles.main_isolate(), source.c_str());
3696   auto callable = tester.GetCallable<Handle<Object>>();
3697   for (size_t i = 0; i < kMaxRegisterForTest; i++) {
3698     Handle<Object> arg = handle(Smi::FromInt(static_cast<int>(i)), isolate);
3699     Handle<Object> return_value = callable(arg).ToHandleChecked();
3700     CHECK(return_value->SameValue(*arg));
3701   }
3702 }
3703 
TEST(InterpreterCallWideRegisters)3704 TEST(InterpreterCallWideRegisters) {
3705   static const int kPeriod = 25;
3706   static const int kLength = 512;
3707   static const int kStartChar = 65;
3708 
3709   for (int pass = 0; pass < 3; pass += 1) {
3710     std::ostringstream os;
3711     for (int i = 0; i < pass * 97; i += 1) {
3712       os << "var x" << i << " = " << i << "\n";
3713     }
3714     os << "return String.fromCharCode(";
3715     os << kStartChar;
3716     for (int i = 1; i < kLength; i += 1) {
3717       os << "," << kStartChar + (i % kPeriod);
3718     }
3719     os << ");";
3720     std::string source = InterpreterTester::SourceForBody(os.str().c_str());
3721     HandleAndZoneScope handles;
3722     InterpreterTester tester(handles.main_isolate(), source.c_str());
3723     auto callable = tester.GetCallable();
3724     Handle<Object> return_val = callable().ToHandleChecked();
3725     Handle<String> return_string = Handle<String>::cast(return_val);
3726     CHECK_EQ(return_string->length(), kLength);
3727     for (int i = 0; i < kLength; i += 1) {
3728       CHECK_EQ(return_string->Get(i), 65 + (i % kPeriod));
3729     }
3730   }
3731 }
3732 
TEST(InterpreterWideParametersPickOne)3733 TEST(InterpreterWideParametersPickOne) {
3734   static const int kParameterCount = 130;
3735   for (int parameter = 0; parameter < 10; parameter++) {
3736     HandleAndZoneScope handles;
3737     i::Isolate* isolate = handles.main_isolate();
3738     std::ostringstream os;
3739     os << "function " << InterpreterTester::function_name() << "(arg) {\n";
3740     os << "  function selector(i";
3741     for (int i = 0; i < kParameterCount; i++) {
3742       os << ","
3743          << "a" << i;
3744     }
3745     os << ") {\n";
3746     os << "  return a" << parameter << ";\n";
3747     os << "  };\n";
3748     os << "  return selector(arg";
3749     for (int i = 0; i < kParameterCount; i++) {
3750       os << "," << i;
3751     }
3752     os << ");";
3753     os << "}\n";
3754 
3755     std::string source = os.str();
3756     InterpreterTester tester(handles.main_isolate(), source.c_str(), "*");
3757     auto callable = tester.GetCallable<Handle<Object>>();
3758     Handle<Object> arg = handle(Smi::FromInt(0xaa55), isolate);
3759     Handle<Object> return_value = callable(arg).ToHandleChecked();
3760     Handle<Smi> actual = Handle<Smi>::cast(return_value);
3761     CHECK_EQ(actual->value(), parameter);
3762   }
3763 }
3764 
TEST(InterpreterWideParametersSummation)3765 TEST(InterpreterWideParametersSummation) {
3766   static int kParameterCount = 200;
3767   static int kBaseValue = 17000;
3768   HandleAndZoneScope handles;
3769   i::Isolate* isolate = handles.main_isolate();
3770   std::ostringstream os;
3771   os << "function " << InterpreterTester::function_name() << "(arg) {\n";
3772   os << "  function summation(i";
3773   for (int i = 0; i < kParameterCount; i++) {
3774     os << ","
3775        << "a" << i;
3776   }
3777   os << ") {\n";
3778   os << "    var sum = " << kBaseValue << ";\n";
3779   os << "    switch(i) {\n";
3780   for (int i = 0; i < kParameterCount; i++) {
3781     int j = kParameterCount - i - 1;
3782     os << "      case " << j << ": sum += a" << j << ";\n";
3783   }
3784   os << "  }\n";
3785   os << "    return sum;\n";
3786   os << "  };\n";
3787   os << "  return summation(arg";
3788   for (int i = 0; i < kParameterCount; i++) {
3789     os << "," << i;
3790   }
3791   os << ");";
3792   os << "}\n";
3793 
3794   std::string source = os.str();
3795   InterpreterTester tester(handles.main_isolate(), source.c_str(), "*");
3796   auto callable = tester.GetCallable<Handle<Object>>();
3797   for (int i = 0; i < kParameterCount; i++) {
3798     Handle<Object> arg = handle(Smi::FromInt(i), isolate);
3799     Handle<Object> return_value = callable(arg).ToHandleChecked();
3800     int expected = kBaseValue + i * (i + 1) / 2;
3801     Handle<Smi> actual = Handle<Smi>::cast(return_value);
3802     CHECK_EQ(actual->value(), expected);
3803   }
3804 }
3805 
TEST(InterpreterDoExpression)3806 TEST(InterpreterDoExpression) {
3807   bool old_flag = FLAG_harmony_do_expressions;
3808   FLAG_harmony_do_expressions = true;
3809 
3810   HandleAndZoneScope handles;
3811   i::Isolate* isolate = handles.main_isolate();
3812   Factory* factory = isolate->factory();
3813 
3814   std::pair<const char*, Handle<Object>> do_expr[] = {
3815       {"var a = do {}; return a;", factory->undefined_value()},
3816       {"var a = do { var x = 100; }; return a;", factory->undefined_value()},
3817       {"var a = do { var x = 100; }; return a;", factory->undefined_value()},
3818       {"var a = do { var x = 100; x++; }; return a;",
3819        handle(Smi::FromInt(100), isolate)},
3820       {"var i = 0; for (; i < 5;) { i = do { if (i == 3) { break; }; i + 1; }};"
3821        "return i;",
3822        handle(Smi::FromInt(3), isolate)},
3823   };
3824 
3825   for (size_t i = 0; i < arraysize(do_expr); i++) {
3826     std::string source(InterpreterTester::SourceForBody(do_expr[i].first));
3827     InterpreterTester tester(handles.main_isolate(), source.c_str());
3828     auto callable = tester.GetCallable<>();
3829 
3830     Handle<i::Object> return_value = callable().ToHandleChecked();
3831     CHECK(return_value->SameValue(*do_expr[i].second));
3832   }
3833 
3834   FLAG_harmony_do_expressions = old_flag;
3835 }
3836 
TEST(InterpreterWithStatement)3837 TEST(InterpreterWithStatement) {
3838   HandleAndZoneScope handles;
3839   i::Isolate* isolate = handles.main_isolate();
3840 
3841   std::pair<const char*, Handle<Object>> with_stmt[] = {
3842       {"with({x:42}) return x;", handle(Smi::FromInt(42), isolate)},
3843       {"with({}) { var y = 10; return y;}", handle(Smi::FromInt(10), isolate)},
3844       {"var y = {x:42};"
3845        " function inner() {"
3846        "   var x = 20;"
3847        "   with(y) return x;"
3848        "}"
3849        "return inner();",
3850        handle(Smi::FromInt(42), isolate)},
3851       {"var y = {x:42};"
3852        " function inner(o) {"
3853        "   var x = 20;"
3854        "   with(o) return x;"
3855        "}"
3856        "return inner(y);",
3857        handle(Smi::FromInt(42), isolate)},
3858   };
3859 
3860   for (size_t i = 0; i < arraysize(with_stmt); i++) {
3861     std::string source(InterpreterTester::SourceForBody(with_stmt[i].first));
3862     InterpreterTester tester(handles.main_isolate(), source.c_str());
3863     auto callable = tester.GetCallable<>();
3864 
3865     Handle<i::Object> return_value = callable().ToHandleChecked();
3866     CHECK(return_value->SameValue(*with_stmt[i].second));
3867   }
3868 }
3869 
TEST(InterpreterClassLiterals)3870 TEST(InterpreterClassLiterals) {
3871   HandleAndZoneScope handles;
3872   i::Isolate* isolate = handles.main_isolate();
3873   std::pair<const char*, Handle<Object>> examples[] = {
3874       {"class C {\n"
3875        "  constructor(x) { this.x_ = x; }\n"
3876        "  method() { return this.x_; }\n"
3877        "}\n"
3878        "return new C(99).method();",
3879        handle(Smi::FromInt(99), isolate)},
3880       {"class C {\n"
3881        "  constructor(x) { this.x_ = x; }\n"
3882        "  static static_method(x) { return x; }\n"
3883        "}\n"
3884        "return C.static_method(101);",
3885        handle(Smi::FromInt(101), isolate)},
3886       {"class C {\n"
3887        "  get x() { return 102; }\n"
3888        "}\n"
3889        "return new C().x",
3890        handle(Smi::FromInt(102), isolate)},
3891       {"class C {\n"
3892        "  static get x() { return 103; }\n"
3893        "}\n"
3894        "return C.x",
3895        handle(Smi::FromInt(103), isolate)},
3896       {"class C {\n"
3897        "  constructor() { this.x_ = 0; }"
3898        "  set x(value) { this.x_ = value; }\n"
3899        "  get x() { return this.x_; }\n"
3900        "}\n"
3901        "var c = new C();"
3902        "c.x = 104;"
3903        "return c.x;",
3904        handle(Smi::FromInt(104), isolate)},
3905       {"var x = 0;"
3906        "class C {\n"
3907        "  static set x(value) { x = value; }\n"
3908        "  static get x() { return x; }\n"
3909        "}\n"
3910        "C.x = 105;"
3911        "return C.x;",
3912        handle(Smi::FromInt(105), isolate)},
3913       {"var method = 'f';"
3914        "class C {\n"
3915        "  [method]() { return 106; }\n"
3916        "}\n"
3917        "return new C().f();",
3918        handle(Smi::FromInt(106), isolate)},
3919   };
3920 
3921   for (size_t i = 0; i < arraysize(examples); ++i) {
3922     std::string source(InterpreterTester::SourceForBody(examples[i].first));
3923     InterpreterTester tester(handles.main_isolate(), source.c_str(), "*");
3924     auto callable = tester.GetCallable<>();
3925 
3926     Handle<i::Object> return_value = callable().ToHandleChecked();
3927     CHECK(return_value->SameValue(*examples[i].second));
3928   }
3929 }
3930 
TEST(InterpreterClassAndSuperClass)3931 TEST(InterpreterClassAndSuperClass) {
3932   HandleAndZoneScope handles;
3933   i::Isolate* isolate = handles.main_isolate();
3934   std::pair<const char*, Handle<Object>> examples[] = {
3935       {"class A {\n"
3936        "  constructor(x) { this.x_ = x; }\n"
3937        "  method() { return this.x_; }\n"
3938        "}\n"
3939        "class B extends A {\n"
3940        "   constructor(x, y) { super(x); this.y_ = y; }\n"
3941        "   method() { return super.method() + 1; }\n"
3942        "}\n"
3943        "return new B(998, 0).method();\n",
3944        handle(Smi::FromInt(999), isolate)},
3945       {"class A {\n"
3946        "  constructor() { this.x_ = 2; this.y_ = 3; }\n"
3947        "}\n"
3948        "class B extends A {\n"
3949        "  constructor() { super(); }"
3950        "  method() { this.x_++; this.y_++; return this.x_ + this.y_; }\n"
3951        "}\n"
3952        "return new B().method();\n",
3953        handle(Smi::FromInt(7), isolate)},
3954       {"var calls = 0;\n"
3955        "class B {}\n"
3956        "B.prototype.x = 42;\n"
3957        "class C extends B {\n"
3958        "  constructor() {\n"
3959        "    super();\n"
3960        "    calls++;\n"
3961        "  }\n"
3962        "}\n"
3963        "new C;\n"
3964        "return calls;\n",
3965        handle(Smi::FromInt(1), isolate)},
3966       {"class A {\n"
3967        "  method() { return 1; }\n"
3968        "  get x() { return 2; }\n"
3969        "}\n"
3970        "class B extends A {\n"
3971        "  method() { return super.x === 2 ? super.method() : -1; }\n"
3972        "}\n"
3973        "return new B().method();\n",
3974        handle(Smi::FromInt(1), isolate)},
3975       {"var object = { setY(v) { super.y = v; }};\n"
3976        "object.setY(10);\n"
3977        "return object.y;\n",
3978        handle(Smi::FromInt(10), isolate)},
3979   };
3980 
3981   for (size_t i = 0; i < arraysize(examples); ++i) {
3982     std::string source(InterpreterTester::SourceForBody(examples[i].first));
3983     InterpreterTester tester(handles.main_isolate(), source.c_str(), "*");
3984     auto callable = tester.GetCallable<>();
3985     Handle<i::Object> return_value = callable().ToHandleChecked();
3986     CHECK(return_value->SameValue(*examples[i].second));
3987   }
3988 }
3989 
TEST(InterpreterConstDeclaration)3990 TEST(InterpreterConstDeclaration) {
3991   HandleAndZoneScope handles;
3992   i::Isolate* isolate = handles.main_isolate();
3993   i::Factory* factory = isolate->factory();
3994 
3995   std::pair<const char*, Handle<Object>> const_decl[] = {
3996       {"const x = 3; return x;", handle(Smi::FromInt(3), isolate)},
3997       {"let x = 10; x = x + 20; return x;", handle(Smi::FromInt(30), isolate)},
3998       {"let x = 10; x = 20; return x;", handle(Smi::FromInt(20), isolate)},
3999       {"let x; x = 20; return x;", handle(Smi::FromInt(20), isolate)},
4000       {"let x; return x;", factory->undefined_value()},
4001       {"var x = 10; { let x = 30; } return x;",
4002        handle(Smi::FromInt(10), isolate)},
4003       {"let x = 10; { let x = 20; } return x;",
4004        handle(Smi::FromInt(10), isolate)},
4005       {"var x = 10; eval('let x = 20;'); return x;",
4006        handle(Smi::FromInt(10), isolate)},
4007       {"var x = 10; eval('const x = 20;'); return x;",
4008        handle(Smi::FromInt(10), isolate)},
4009       {"var x = 10; { const x = 20; } return x;",
4010        handle(Smi::FromInt(10), isolate)},
4011       {"var x = 10; { const x = 20; return x;} return -1;",
4012        handle(Smi::FromInt(20), isolate)},
4013       {"var a = 10;\n"
4014        "for (var i = 0; i < 10; ++i) {\n"
4015        " const x = i;\n"  // const declarations are block scoped.
4016        " a = a + x;\n"
4017        "}\n"
4018        "return a;\n",
4019        handle(Smi::FromInt(55), isolate)},
4020   };
4021 
4022   // Tests for sloppy mode.
4023   for (size_t i = 0; i < arraysize(const_decl); i++) {
4024     std::string source(InterpreterTester::SourceForBody(const_decl[i].first));
4025     InterpreterTester tester(handles.main_isolate(), source.c_str());
4026     auto callable = tester.GetCallable<>();
4027 
4028     Handle<i::Object> return_value = callable().ToHandleChecked();
4029     CHECK(return_value->SameValue(*const_decl[i].second));
4030   }
4031 
4032   // Tests for strict mode.
4033   for (size_t i = 0; i < arraysize(const_decl); i++) {
4034     std::string strict_body =
4035         "'use strict'; " + std::string(const_decl[i].first);
4036     std::string source(InterpreterTester::SourceForBody(strict_body.c_str()));
4037     InterpreterTester tester(handles.main_isolate(), source.c_str());
4038     auto callable = tester.GetCallable<>();
4039 
4040     Handle<i::Object> return_value = callable().ToHandleChecked();
4041     CHECK(return_value->SameValue(*const_decl[i].second));
4042   }
4043 }
4044 
TEST(InterpreterConstDeclarationLookupSlots)4045 TEST(InterpreterConstDeclarationLookupSlots) {
4046   HandleAndZoneScope handles;
4047   i::Isolate* isolate = handles.main_isolate();
4048   i::Factory* factory = isolate->factory();
4049 
4050   std::pair<const char*, Handle<Object>> const_decl[] = {
4051       {"const x = 3; function f1() {return x;}; return x;",
4052        handle(Smi::FromInt(3), isolate)},
4053       {"let x = 10; x = x + 20; function f1() {return x;}; return x;",
4054        handle(Smi::FromInt(30), isolate)},
4055       {"let x; x = 20; function f1() {return x;}; return x;",
4056        handle(Smi::FromInt(20), isolate)},
4057       {"let x; function f1() {return x;}; return x;",
4058        factory->undefined_value()},
4059   };
4060 
4061   // Tests for sloppy mode.
4062   for (size_t i = 0; i < arraysize(const_decl); i++) {
4063     std::string source(InterpreterTester::SourceForBody(const_decl[i].first));
4064     InterpreterTester tester(handles.main_isolate(), source.c_str());
4065     auto callable = tester.GetCallable<>();
4066 
4067     Handle<i::Object> return_value = callable().ToHandleChecked();
4068     CHECK(return_value->SameValue(*const_decl[i].second));
4069   }
4070 
4071   // Tests for strict mode.
4072   for (size_t i = 0; i < arraysize(const_decl); i++) {
4073     std::string strict_body =
4074         "'use strict'; " + std::string(const_decl[i].first);
4075     std::string source(InterpreterTester::SourceForBody(strict_body.c_str()));
4076     InterpreterTester tester(handles.main_isolate(), source.c_str());
4077     auto callable = tester.GetCallable<>();
4078 
4079     Handle<i::Object> return_value = callable().ToHandleChecked();
4080     CHECK(return_value->SameValue(*const_decl[i].second));
4081   }
4082 }
4083 
TEST(InterpreterConstInLookupContextChain)4084 TEST(InterpreterConstInLookupContextChain) {
4085   HandleAndZoneScope handles;
4086   i::Isolate* isolate = handles.main_isolate();
4087 
4088   const char* prologue =
4089       "function OuterMost() {\n"
4090       "  const outerConst = 10;\n"
4091       "  let outerLet = 20;\n"
4092       "  function Outer() {\n"
4093       "    function Inner() {\n"
4094       "      this.innerFunc = function() { ";
4095   const char* epilogue =
4096       "      }\n"
4097       "    }\n"
4098       "    this.getInnerFunc ="
4099       "         function() {return new Inner().innerFunc;}\n"
4100       "  }\n"
4101       "  this.getOuterFunc ="
4102       "     function() {return new Outer().getInnerFunc();}"
4103       "}\n"
4104       "var f = new OuterMost().getOuterFunc();\n"
4105       "f();\n";
4106   std::pair<const char*, Handle<Object>> const_decl[] = {
4107       {"return outerConst;", handle(Smi::FromInt(10), isolate)},
4108       {"return outerLet;", handle(Smi::FromInt(20), isolate)},
4109       {"outerLet = 30; return outerLet;", handle(Smi::FromInt(30), isolate)},
4110       {"var outerLet = 40; return outerLet;",
4111        handle(Smi::FromInt(40), isolate)},
4112       {"var outerConst = 50; return outerConst;",
4113        handle(Smi::FromInt(50), isolate)},
4114       {"try { outerConst = 30 } catch(e) { return -1; }",
4115        handle(Smi::FromInt(-1), isolate)}};
4116 
4117   for (size_t i = 0; i < arraysize(const_decl); i++) {
4118     std::string script = std::string(prologue) +
4119                          std::string(const_decl[i].first) +
4120                          std::string(epilogue);
4121     InterpreterTester tester(handles.main_isolate(), script.c_str(), "*");
4122     auto callable = tester.GetCallable<>();
4123 
4124     Handle<i::Object> return_value = callable().ToHandleChecked();
4125     CHECK(return_value->SameValue(*const_decl[i].second));
4126   }
4127 }
4128 
TEST(InterpreterIllegalConstDeclaration)4129 TEST(InterpreterIllegalConstDeclaration) {
4130   HandleAndZoneScope handles;
4131 
4132   std::pair<const char*, const char*> const_decl[] = {
4133       {"const x = x = 10 + 3; return x;",
4134        "Uncaught ReferenceError: x is not defined"},
4135       {"const x = 10; x = 20; return x;",
4136        "Uncaught TypeError: Assignment to constant variable."},
4137       {"const x = 10; { x = 20; } return x;",
4138        "Uncaught TypeError: Assignment to constant variable."},
4139       {"const x = 10; eval('x = 20;'); return x;",
4140        "Uncaught TypeError: Assignment to constant variable."},
4141       {"let x = x + 10; return x;",
4142        "Uncaught ReferenceError: x is not defined"},
4143       {"'use strict'; (function f1() { f1 = 123; })() ",
4144        "Uncaught TypeError: Assignment to constant variable."},
4145   };
4146 
4147   // Tests for sloppy mode.
4148   for (size_t i = 0; i < arraysize(const_decl); i++) {
4149     std::string source(InterpreterTester::SourceForBody(const_decl[i].first));
4150     InterpreterTester tester(handles.main_isolate(), source.c_str());
4151     v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
4152     v8::Local<v8::String> expected_string = v8_str(const_decl[i].second);
4153     CHECK(
4154         message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
4155             .FromJust());
4156   }
4157 
4158   // Tests for strict mode.
4159   for (size_t i = 0; i < arraysize(const_decl); i++) {
4160     std::string strict_body =
4161         "'use strict'; " + std::string(const_decl[i].first);
4162     std::string source(InterpreterTester::SourceForBody(strict_body.c_str()));
4163     InterpreterTester tester(handles.main_isolate(), source.c_str());
4164     v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
4165     v8::Local<v8::String> expected_string = v8_str(const_decl[i].second);
4166     CHECK(
4167         message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
4168             .FromJust());
4169   }
4170 }
4171 
TEST(InterpreterGenerators)4172 TEST(InterpreterGenerators) {
4173   bool old_flag = FLAG_ignition_generators;
4174   FLAG_ignition_generators = true;
4175 
4176   HandleAndZoneScope handles;
4177   i::Isolate* isolate = handles.main_isolate();
4178   i::Factory* factory = isolate->factory();
4179 
4180   std::pair<const char*, Handle<Object>> tests[] = {
4181       {"function* f() { }; return f().next().value",
4182        factory->undefined_value()},
4183       {"function* f() { yield 42 }; return f().next().value",
4184        factory->NewNumberFromInt(42)},
4185       {"function* f() { for (let x of [42]) yield x}; return f().next().value",
4186        factory->NewNumberFromInt(42)},
4187   };
4188 
4189   for (size_t i = 0; i < arraysize(tests); i++) {
4190     std::string source(InterpreterTester::SourceForBody(tests[i].first));
4191     InterpreterTester tester(handles.main_isolate(), source.c_str());
4192     auto callable = tester.GetCallable<>();
4193 
4194     Handle<i::Object> return_value = callable().ToHandleChecked();
4195     CHECK(return_value->SameValue(*tests[i].second));
4196   }
4197 
4198   FLAG_ignition_generators = old_flag;
4199 }
4200 
4201 }  // namespace interpreter
4202 }  // namespace internal
4203 }  // namespace v8
4204