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