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