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