blob: 2c06da26a16b5ca2f0097f48bfb409e292b3f9dc [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/compiler.h"
8#include "src/interpreter/bytecode-array-iterator.h"
9#include "src/interpreter/bytecode-generator.h"
10#include "src/interpreter/interpreter.h"
11#include "test/cctest/cctest.h"
12#include "test/cctest/test-feedback-vector.h"
13
14namespace v8 {
15namespace internal {
16namespace interpreter {
17
18class BytecodeGeneratorHelper {
19 public:
20 const char* kFunctionName = "f";
21
22 static const int kLastParamIndex =
23 -InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize;
24
25 BytecodeGeneratorHelper() {
26 i::FLAG_ignition = true;
27 i::FLAG_ignition_fake_try_catch = true;
28 i::FLAG_ignition_fallback_on_eval_and_catch = false;
29 i::FLAG_ignition_filter = StrDup(kFunctionName);
30 i::FLAG_always_opt = false;
31 i::FLAG_allow_natives_syntax = true;
32 i::FLAG_legacy_const = true;
33 CcTest::i_isolate()->interpreter()->Initialize();
34 }
35
36 Isolate* isolate() { return CcTest::i_isolate(); }
37 Factory* factory() { return CcTest::i_isolate()->factory(); }
38
39 Handle<BytecodeArray> MakeTopLevelBytecode(const char* source) {
40 const char* old_ignition_filter = i::FLAG_ignition_filter;
41 i::FLAG_ignition_filter = "*";
42 Local<v8::Script> script = v8_compile(source);
43 i::FLAG_ignition_filter = old_ignition_filter;
44 i::Handle<i::JSFunction> js_function = v8::Utils::OpenHandle(*script);
45 return handle(js_function->shared()->bytecode_array(), CcTest::i_isolate());
46 }
47
48 Handle<BytecodeArray> MakeBytecode(const char* script,
49 const char* function_name) {
50 CompileRun(script);
51 v8::Local<v8::Context> context =
52 v8::Isolate::GetCurrent()->GetCurrentContext();
53 Local<Function> function = Local<Function>::Cast(
54 CcTest::global()->Get(context, v8_str(function_name)).ToLocalChecked());
55 i::Handle<i::JSFunction> js_function =
56 i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*function));
57 return handle(js_function->shared()->bytecode_array(), CcTest::i_isolate());
58 }
59
60 Handle<BytecodeArray> MakeBytecode(const char* script, const char* filter,
61 const char* function_name) {
62 const char* old_ignition_filter = i::FLAG_ignition_filter;
63 i::FLAG_ignition_filter = filter;
64 Handle<BytecodeArray> return_val = MakeBytecode(script, function_name);
65 i::FLAG_ignition_filter = old_ignition_filter;
66 return return_val;
67 }
68
69 Handle<BytecodeArray> MakeBytecodeForFunctionBody(const char* body) {
70 static const char kFormat[] = "function %s() { %s }\n%s();";
71 static const int kFormatLength = arraysize(kFormat);
72 int length = kFormatLength + 2 * StrLength(kFunctionName) + StrLength(body);
73 ScopedVector<char> program(length);
74 length = SNPrintF(program, kFormat, kFunctionName, body, kFunctionName);
75 CHECK_GT(length, 0);
76 return MakeBytecode(program.start(), kFunctionName);
77 }
78
79 Handle<BytecodeArray> MakeBytecodeForFunction(const char* function) {
80 ScopedVector<char> program(3072);
81 SNPrintF(program, "%s\n%s();", function, kFunctionName);
82 return MakeBytecode(program.start(), kFunctionName);
83 }
84
85 Handle<BytecodeArray> MakeBytecodeForFunctionNoFilter(const char* function) {
86 ScopedVector<char> program(3072);
87 SNPrintF(program, "%s\n%s();", function, kFunctionName);
88 return MakeBytecode(program.start(), "*", kFunctionName);
89 }
90};
91
92
93// Helper macros for handcrafting bytecode sequences.
94#define B(x) static_cast<uint8_t>(Bytecode::k##x)
95#define U8(x) static_cast<uint8_t>((x) & 0xff)
96#define R(x) static_cast<uint8_t>(-(x) & 0xff)
97#define A(x, n) R(helper.kLastParamIndex - (n) + 1 + (x))
98#define THIS(n) A(0, n)
99#if defined(V8_TARGET_LITTLE_ENDIAN)
100#define U16(x) static_cast<uint8_t>((x) & 0xff), \
101 static_cast<uint8_t>(((x) >> kBitsPerByte) & 0xff)
102#define U16I(x) static_cast<uint8_t>((x) & 0xff), \
103 static_cast<uint8_t>(((x++) >> kBitsPerByte) & 0xff)
104#elif defined(V8_TARGET_BIG_ENDIAN)
105#define U16(x) static_cast<uint8_t>(((x) >> kBitsPerByte) & 0xff), \
106 static_cast<uint8_t>((x) & 0xff)
107#define U16I(x) static_cast<uint8_t>(((x) >> kBitsPerByte) & 0xff), \
108 static_cast<uint8_t>((x++) & 0xff)
109#else
110#error Unknown byte ordering
111#endif
112
113#define XSTR(A) #A
114#define STR(A) XSTR(A)
115
116#define COMMA() ,
117#define SPACE()
118#define UNIQUE_VAR() "var a" STR(__COUNTER__) " = 0;\n"
119
120#define REPEAT_2(SEP, ...) \
121 __VA_ARGS__ SEP() __VA_ARGS__
122#define REPEAT_4(SEP, ...) \
123 REPEAT_2(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__)
124#define REPEAT_8(SEP, ...) \
125 REPEAT_4(SEP, __VA_ARGS__) SEP() REPEAT_4(SEP, __VA_ARGS__)
126#define REPEAT_16(SEP, ...) \
127 REPEAT_8(SEP, __VA_ARGS__) SEP() REPEAT_8(SEP, __VA_ARGS__)
128#define REPEAT_32(SEP, ...) \
129 REPEAT_16(SEP, __VA_ARGS__) SEP() REPEAT_16(SEP, __VA_ARGS__)
130#define REPEAT_64(SEP, ...) \
131 REPEAT_32(SEP, __VA_ARGS__) SEP() REPEAT_32(SEP, __VA_ARGS__)
132#define REPEAT_128(SEP, ...) \
133 REPEAT_64(SEP, __VA_ARGS__) SEP() REPEAT_64(SEP, __VA_ARGS__)
134#define REPEAT_256(SEP, ...) \
135 REPEAT_128(SEP, __VA_ARGS__) SEP() REPEAT_128(SEP, __VA_ARGS__)
136
137#define REPEAT_127(SEP, ...) \
138 REPEAT_64(SEP, __VA_ARGS__) SEP() REPEAT_32(SEP, __VA_ARGS__) SEP() \
139 REPEAT_16(SEP, __VA_ARGS__) SEP() REPEAT_8(SEP, __VA_ARGS__) SEP() \
140 REPEAT_4(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__) SEP() \
141 __VA_ARGS__
142
143#define REPEAT_249(SEP, ...) \
144 REPEAT_127(SEP, __VA_ARGS__) SEP() REPEAT_64(SEP, __VA_ARGS__) SEP() \
145 REPEAT_32(SEP, __VA_ARGS__) SEP() REPEAT_16(SEP, __VA_ARGS__) SEP() \
146 REPEAT_8(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__)
147
148#define REPEAT_249_UNIQUE_VARS() \
149UNIQUE_VAR() REPEAT_127(UNIQUE_VAR) UNIQUE_VAR() REPEAT_64(UNIQUE_VAR) \
150UNIQUE_VAR() REPEAT_32(UNIQUE_VAR) UNIQUE_VAR() REPEAT_16(UNIQUE_VAR) \
151UNIQUE_VAR() REPEAT_8(UNIQUE_VAR) UNIQUE_VAR() REPEAT_2(UNIQUE_VAR)
152
153// Structure for containing expected bytecode snippets.
154template<typename T, int C = 6>
155struct ExpectedSnippet {
156 const char* code_snippet;
157 int frame_size;
158 int parameter_count;
159 int bytecode_length;
160 const uint8_t bytecode[2048];
161 int constant_count;
162 T constants[C];
163};
164
165
166static void CheckConstant(int expected, Object* actual) {
167 CHECK_EQ(expected, Smi::cast(actual)->value());
168}
169
170
171static void CheckConstant(double expected, Object* actual) {
172 CHECK_EQ(expected, HeapNumber::cast(actual)->value());
173}
174
175
176static void CheckConstant(const char* expected, Object* actual) {
177 Handle<String> expected_string =
178 CcTest::i_isolate()->factory()->NewStringFromAsciiChecked(expected);
179 CHECK(String::cast(actual)->Equals(*expected_string));
180}
181
182
183static void CheckConstant(Handle<Object> expected, Object* actual) {
184 CHECK(actual == *expected || expected->StrictEquals(actual));
185}
186
187
188static void CheckConstant(InstanceType expected, Object* actual) {
189 CHECK_EQ(expected, HeapObject::cast(actual)->map()->instance_type());
190}
191
192
193template <typename T, int C>
194static void CheckBytecodeArrayEqual(const ExpectedSnippet<T, C>& expected,
195 Handle<BytecodeArray> actual) {
196 CHECK_EQ(expected.frame_size, actual->frame_size());
197 CHECK_EQ(expected.parameter_count, actual->parameter_count());
198 CHECK_EQ(expected.bytecode_length, actual->length());
199 if (expected.constant_count == 0) {
200 CHECK_EQ(CcTest::heap()->empty_fixed_array(), actual->constant_pool());
201 } else {
202 CHECK_EQ(expected.constant_count, actual->constant_pool()->length());
203 for (int i = 0; i < expected.constant_count; i++) {
204 CheckConstant(expected.constants[i], actual->constant_pool()->get(i));
205 }
206 }
207
208 BytecodeArrayIterator iterator(actual);
209 int i = 0;
210 while (!iterator.done()) {
211 int bytecode_index = i++;
212 Bytecode bytecode = iterator.current_bytecode();
213 if (Bytecodes::ToByte(bytecode) != expected.bytecode[bytecode_index]) {
214 std::ostringstream stream;
215 stream << "Check failed: expected bytecode [" << bytecode_index
216 << "] to be " << Bytecodes::ToString(static_cast<Bytecode>(
217 expected.bytecode[bytecode_index]))
218 << " but got " << Bytecodes::ToString(bytecode);
219 FATAL(stream.str().c_str());
220 }
221 for (int j = 0; j < Bytecodes::NumberOfOperands(bytecode); ++j) {
222 OperandType operand_type = Bytecodes::GetOperandType(bytecode, j);
223 int operand_index = i;
224 i += static_cast<int>(Bytecodes::SizeOfOperand(operand_type));
225 uint32_t raw_operand = iterator.GetRawOperand(j, operand_type);
226 uint32_t expected_operand;
227 switch (Bytecodes::SizeOfOperand(operand_type)) {
228 case OperandSize::kNone:
229 UNREACHABLE();
230 return;
231 case OperandSize::kByte:
232 expected_operand =
233 static_cast<uint32_t>(expected.bytecode[operand_index]);
234 break;
235 case OperandSize::kShort:
236 expected_operand =
237 ReadUnalignedUInt16(&expected.bytecode[operand_index]);
238 break;
239 default:
240 UNREACHABLE();
241 return;
242 }
243 if (raw_operand != expected_operand) {
244 std::ostringstream stream;
245 stream << "Check failed: expected operand [" << j << "] for bytecode ["
246 << bytecode_index << "] to be "
247 << static_cast<unsigned int>(expected_operand) << " but got "
248 << static_cast<unsigned int>(raw_operand);
249 FATAL(stream.str().c_str());
250 }
251 }
252 iterator.Advance();
253 }
254}
255
256
257TEST(PrimitiveReturnStatements) {
258 InitializedHandleScope handle_scope;
259 BytecodeGeneratorHelper helper;
260
261 ExpectedSnippet<int> snippets[] = {
262 {"", 0, 1, 2, {B(LdaUndefined), B(Return)}, 0},
263 {"return;", 0, 1, 2, {B(LdaUndefined), B(Return)}, 0},
264 {"return null;", 0, 1, 2, {B(LdaNull), B(Return)}, 0},
265 {"return true;", 0, 1, 2, {B(LdaTrue), B(Return)}, 0},
266 {"return false;", 0, 1, 2, {B(LdaFalse), B(Return)}, 0},
267 {"return 0;", 0, 1, 2, {B(LdaZero), B(Return)}, 0},
268 {"return +1;", 0, 1, 3, {B(LdaSmi8), U8(1), B(Return)}, 0},
269 {"return -1;", 0, 1, 3, {B(LdaSmi8), U8(-1), B(Return)}, 0},
270 {"return +127;", 0, 1, 3, {B(LdaSmi8), U8(127), B(Return)}, 0},
271 {"return -128;", 0, 1, 3, {B(LdaSmi8), U8(-128), B(Return)}, 0},
272 };
273
274 for (size_t i = 0; i < arraysize(snippets); i++) {
275 Handle<BytecodeArray> bytecode_array =
276 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
277 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
278 }
279}
280
281
282TEST(PrimitiveExpressions) {
283 InitializedHandleScope handle_scope;
284 BytecodeGeneratorHelper helper;
285
286 ExpectedSnippet<int> snippets[] = {
287 {"var x = 0; return x;",
288 kPointerSize,
289 1,
290 4,
291 {B(LdaZero), //
292 B(Star), R(0), //
293 B(Return)},
294 0},
295 {"var x = 0; return x + 3;",
296 2 * kPointerSize,
297 1,
298 10,
299 {B(LdaZero), //
300 B(Star), R(0), //
301 B(Star), R(1), //
302 B(LdaSmi8), U8(3), //
303 B(Add), R(1), //
304 B(Return)},
305 0},
306 {"var x = 0; return x - 3;",
307 2 * kPointerSize,
308 1,
309 10,
310 {B(LdaZero), //
311 B(Star), R(0), //
312 B(Star), R(1), //
313 B(LdaSmi8), U8(3), //
314 B(Sub), R(1), //
315 B(Return)},
316 0},
317 {"var x = 4; return x * 3;",
318 2 * kPointerSize,
319 1,
320 11,
321 {B(LdaSmi8), U8(4), //
322 B(Star), R(0), //
323 B(Star), R(1), //
324 B(LdaSmi8), U8(3), //
325 B(Mul), R(1), //
326 B(Return)},
327 0},
328 {"var x = 4; return x / 3;",
329 2 * kPointerSize,
330 1,
331 11,
332 {B(LdaSmi8), U8(4), //
333 B(Star), R(0), //
334 B(Star), R(1), //
335 B(LdaSmi8), U8(3), //
336 B(Div), R(1), //
337 B(Return)},
338 0},
339 {"var x = 4; return x % 3;",
340 2 * kPointerSize,
341 1,
342 11,
343 {B(LdaSmi8), U8(4), //
344 B(Star), R(0), //
345 B(Star), R(1), //
346 B(LdaSmi8), U8(3), //
347 B(Mod), R(1), //
348 B(Return)},
349 0},
350 {"var x = 1; return x | 2;",
351 2 * kPointerSize,
352 1,
353 11,
354 {B(LdaSmi8), U8(1), //
355 B(Star), R(0), //
356 B(Star), R(1), //
357 B(LdaSmi8), U8(2), //
358 B(BitwiseOr), R(1), //
359 B(Return)},
360 0},
361 {"var x = 1; return x ^ 2;",
362 2 * kPointerSize,
363 1,
364 11,
365 {B(LdaSmi8), U8(1), //
366 B(Star), R(0), //
367 B(Star), R(1), //
368 B(LdaSmi8), U8(2), //
369 B(BitwiseXor), R(1), //
370 B(Return)},
371 0},
372 {"var x = 1; return x & 2;",
373 2 * kPointerSize,
374 1,
375 11,
376 {B(LdaSmi8), U8(1), //
377 B(Star), R(0), //
378 B(Star), R(1), //
379 B(LdaSmi8), U8(2), //
380 B(BitwiseAnd), R(1), //
381 B(Return)},
382 0},
383 {"var x = 10; return x << 3;",
384 2 * kPointerSize,
385 1,
386 11,
387 {B(LdaSmi8), U8(10), //
388 B(Star), R(0), //
389 B(Star), R(1), //
390 B(LdaSmi8), U8(3), //
391 B(ShiftLeft), R(1), //
392 B(Return)},
393 0},
394 {"var x = 10; return x >> 3;",
395 2 * kPointerSize,
396 1,
397 11,
398 {B(LdaSmi8), U8(10), //
399 B(Star), R(0), //
400 B(Star), R(1), //
401 B(LdaSmi8), U8(3), //
402 B(ShiftRight), R(1), //
403 B(Return)},
404 0},
405 {"var x = 10; return x >>> 3;",
406 2 * kPointerSize,
407 1,
408 11,
409 {B(LdaSmi8), U8(10), //
410 B(Star), R(0), //
411 B(Star), R(1), //
412 B(LdaSmi8), U8(3), //
413 B(ShiftRightLogical), R(1), //
414 B(Return)},
415 0},
416 {"var x = 0; return (x, 3);",
417 1 * kPointerSize,
418 1,
419 6,
420 {B(LdaZero), //
421 B(Star), R(0), //
422 B(LdaSmi8), U8(3), //
423 B(Return)},
424 0}};
425
426 for (size_t i = 0; i < arraysize(snippets); i++) {
427 Handle<BytecodeArray> bytecode_array =
428 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
429 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
430 }
431}
432
433
434TEST(LogicalExpressions) {
435 InitializedHandleScope handle_scope;
436 BytecodeGeneratorHelper helper;
437
438 ExpectedSnippet<int> snippets[] = {
439 {"var x = 0; return x || 3;",
440 1 * kPointerSize,
441 1,
442 8,
443 {B(LdaZero), //
444 B(Star), R(0), //
445 B(JumpIfToBooleanTrue), U8(4), //
446 B(LdaSmi8), U8(3), //
447 B(Return)},
448 0},
449 {"var x = 0; return (x == 1) || 3;",
450 2 * kPointerSize,
451 1,
452 14,
453 {B(LdaZero), //
454 B(Star), R(0), //
455 B(Star), R(1), //
456 B(LdaSmi8), U8(1), //
457 B(TestEqual), R(1), //
458 B(JumpIfTrue), U8(4), //
459 B(LdaSmi8), U8(3), //
460 B(Return)},
461 0},
462 {"var x = 0; return x && 3;",
463 1 * kPointerSize,
464 1,
465 8,
466 {B(LdaZero), //
467 B(Star), R(0), //
468 B(JumpIfToBooleanFalse), U8(4), //
469 B(LdaSmi8), U8(3), //
470 B(Return)},
471 0},
472 {"var x = 0; return (x == 0) && 3;",
473 2 * kPointerSize,
474 1,
475 13,
476 {B(LdaZero), //
477 B(Star), R(0), //
478 B(Star), R(1), //
479 B(LdaZero), //
480 B(TestEqual), R(1), //
481 B(JumpIfFalse), U8(4), //
482 B(LdaSmi8), U8(3), //
483 B(Return)},
484 0},
485 {"var x = 0; return x || (1, 2, 3);",
486 1 * kPointerSize,
487 1,
488 8,
489 {B(LdaZero), //
490 B(Star), R(0), //
491 B(JumpIfToBooleanTrue), U8(4), //
492 B(LdaSmi8), U8(3), //
493 B(Return)},
494 0},
495 {"var a = 2, b = 3, c = 4; return a || (a, b, a, b, c = 5, 3);",
496 3 * kPointerSize,
497 1,
498 31,
499 {B(LdaSmi8), U8(2), //
500 B(Star), R(0), //
501 B(LdaSmi8), U8(3), //
502 B(Star), R(1), //
503 B(LdaSmi8), U8(4), //
504 B(Star), R(2), //
505 B(Ldar), R(0), //
506 B(JumpIfToBooleanTrue), U8(16), //
507 B(Ldar), R(0), //
508 B(Ldar), R(1), //
509 B(Ldar), R(0), //
510 B(Ldar), R(1), //
511 B(LdaSmi8), U8(5), //
512 B(Star), R(2), //
513 B(LdaSmi8), U8(3), //
514 B(Return)},
515 0},
516 {"var x = 1; var a = 2, b = 3; return x || ("
517 REPEAT_32(SPACE, "a = 1, b = 2, ")
518 "3);",
519 3 * kPointerSize,
520 1,
521 275,
522 {B(LdaSmi8), U8(1), //
523 B(Star), R(0), //
524 B(LdaSmi8), U8(2), //
525 B(Star), R(1), //
526 B(LdaSmi8), U8(3), //
527 B(Star), R(2), //
528 B(Ldar), R(0), //
529 B(JumpIfToBooleanTrueConstant), U8(0), //
530 REPEAT_32(COMMA, //
531 B(LdaSmi8), U8(1), //
532 B(Star), R(1), //
533 B(LdaSmi8), U8(2), //
534 B(Star), R(2)), //
535 B(LdaSmi8), U8(3), //
536 B(Return)},
537 1,
538 {260, 0, 0, 0}},
539 {"var x = 0; var a = 2, b = 3; return x && ("
540 REPEAT_32(SPACE, "a = 1, b = 2, ")
541 "3);",
542 3 * kPointerSize,
543 1,
544 274,
545 {B(LdaZero), //
546 B(Star), R(0), //
547 B(LdaSmi8), U8(2), //
548 B(Star), R(1), //
549 B(LdaSmi8), U8(3), //
550 B(Star), R(2), //
551 B(Ldar), R(0), //
552 B(JumpIfToBooleanFalseConstant), U8(0), //
553 REPEAT_32(COMMA, //
554 B(LdaSmi8), U8(1), //
555 B(Star), R(1), //
556 B(LdaSmi8), U8(2), //
557 B(Star), R(2)), //
558 B(LdaSmi8), U8(3), //
559 B(Return)}, //
560 1,
561 {260, 0, 0, 0}},
562 {"var x = 1; var a = 2, b = 3; return (x > 3) || ("
563 REPEAT_32(SPACE, "a = 1, b = 2, ")
564 "3);",
565 4 * kPointerSize,
566 1,
567 281,
568 {B(LdaSmi8), U8(1), //
569 B(Star), R(0), //
570 B(LdaSmi8), U8(2), //
571 B(Star), R(1), //
572 B(LdaSmi8), U8(3), //
573 B(Star), R(2), //
574 B(Ldar), R(0), //
575 B(Star), R(3), //
576 B(LdaSmi8), U8(3), //
577 B(TestGreaterThan), R(3), //
578 B(JumpIfTrueConstant), U8(0), //
579 REPEAT_32(COMMA, //
580 B(LdaSmi8), U8(1), //
581 B(Star), R(1), //
582 B(LdaSmi8), U8(2), //
583 B(Star), R(2)), //
584 B(LdaSmi8), U8(3), //
585 B(Return)},
586 1,
587 {260, 0, 0, 0}},
588 {"var x = 0; var a = 2, b = 3; return (x < 5) && ("
589 REPEAT_32(SPACE, "a = 1, b = 2, ")
590 "3);",
591 4 * kPointerSize,
592 1,
593 280,
594 {B(LdaZero), //
595 B(Star), R(0), //
596 B(LdaSmi8), U8(2), //
597 B(Star), R(1), //
598 B(LdaSmi8), U8(3), //
599 B(Star), R(2), //
600 B(Ldar), R(0), //
601 B(Star), R(3), //
602 B(LdaSmi8), U8(5), //
603 B(TestLessThan), R(3), //
604 B(JumpIfFalseConstant), U8(0), //
605 REPEAT_32(COMMA, //
606 B(LdaSmi8), U8(1), //
607 B(Star), R(1), //
608 B(LdaSmi8), U8(2), //
609 B(Star), R(2)), //
610 B(LdaSmi8), U8(3), //
611 B(Return)},
612 1,
613 {260, 0, 0, 0}},
614 {"return 0 && 3;",
615 0 * kPointerSize,
616 1,
617 2,
618 {B(LdaZero), //
619 B(Return)},
620 0},
621 {"return 1 || 3;",
622 0 * kPointerSize,
623 1,
624 3,
625 {B(LdaSmi8), U8(1), //
626 B(Return)},
627 0},
628 {"var x = 1; return x && 3 || 0, 1;",
629 1 * kPointerSize,
630 1,
631 14,
632 {B(LdaSmi8), U8(1), //
633 B(Star), R(0), //
634 B(JumpIfToBooleanFalse), U8(4), //
635 B(LdaSmi8), U8(3), //
636 B(JumpIfToBooleanTrue), U8(3), //
637 B(LdaZero), //
638 B(LdaSmi8), U8(1), //
639 B(Return)},
640 0}};
641
642 for (size_t i = 0; i < arraysize(snippets); i++) {
643 Handle<BytecodeArray> bytecode_array =
644 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
645 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
646 }
647}
648
649
650TEST(Parameters) {
651 InitializedHandleScope handle_scope;
652 BytecodeGeneratorHelper helper;
653
654 ExpectedSnippet<int> snippets[] = {
655 {"function f() { return this; }",
656 0,
657 1,
658 3,
659 {B(Ldar), THIS(1), B(Return)},
660 0},
661 {"function f(arg1) { return arg1; }",
662 0,
663 2,
664 3,
665 {B(Ldar), A(1, 2), B(Return)},
666 0},
667 {"function f(arg1) { return this; }",
668 0,
669 2,
670 3,
671 {B(Ldar), THIS(2), B(Return)},
672 0},
673 {"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return arg4; }",
674 0,
675 8,
676 3,
677 {B(Ldar), A(4, 8), B(Return)},
678 0},
679 {"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return this; }",
680 0,
681 8,
682 3,
683 {B(Ldar), THIS(8), B(Return)},
684 0},
685 {"function f(arg1) { arg1 = 1; }",
686 0,
687 2,
688 6,
689 {B(LdaSmi8), U8(1), //
690 B(Star), A(1, 2), //
691 B(LdaUndefined), //
692 B(Return)},
693 0},
694 {"function f(arg1, arg2, arg3, arg4) { arg2 = 1; }",
695 0,
696 5,
697 6,
698 {B(LdaSmi8), U8(1), //
699 B(Star), A(2, 5), //
700 B(LdaUndefined), //
701 B(Return)},
702 0},
703 };
704
705 for (size_t i = 0; i < arraysize(snippets); i++) {
706 Handle<BytecodeArray> bytecode_array =
707 helper.MakeBytecodeForFunction(snippets[i].code_snippet);
708 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
709 }
710}
711
712
713TEST(IntegerConstants) {
714 InitializedHandleScope handle_scope;
715 BytecodeGeneratorHelper helper;
716
717 ExpectedSnippet<int> snippets[] = {
718 {"return 12345678;",
719 0,
720 1,
721 3,
722 {
723 B(LdaConstant), U8(0), //
724 B(Return) //
725 },
726 1,
727 {12345678}},
728 {"var a = 1234; return 5678;",
729 1 * kPointerSize,
730 1,
731 7,
732 {
733 B(LdaConstant), U8(0), //
734 B(Star), R(0), //
735 B(LdaConstant), U8(1), //
736 B(Return) //
737 },
738 2,
739 {1234, 5678}},
740 {"var a = 1234; return 1234;",
741 1 * kPointerSize,
742 1,
743 7,
744 {
745 B(LdaConstant), U8(0), //
746 B(Star), R(0), //
747 B(LdaConstant), U8(0), //
748 B(Return) //
749 },
750 1,
751 {1234}}};
752
753 for (size_t i = 0; i < arraysize(snippets); i++) {
754 Handle<BytecodeArray> bytecode_array =
755 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
756 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
757 }
758}
759
760
761TEST(HeapNumberConstants) {
762 InitializedHandleScope handle_scope;
763 BytecodeGeneratorHelper helper;
764
765 int wide_idx = 0;
766
767 ExpectedSnippet<double, 257> snippets[] = {
768 {"return 1.2;",
769 0,
770 1,
771 3,
772 {
773 B(LdaConstant), U8(0), //
774 B(Return) //
775 },
776 1,
777 {1.2}},
778 {"var a = 1.2; return 2.6;",
779 1 * kPointerSize,
780 1,
781 7,
782 {
783 B(LdaConstant), U8(0), //
784 B(Star), R(0), //
785 B(LdaConstant), U8(1), //
786 B(Return) //
787 },
788 2,
789 {1.2, 2.6}},
790 {"var a = 3.14; return 3.14;",
791 1 * kPointerSize,
792 1,
793 7,
794 {
795 B(LdaConstant), U8(0), //
796 B(Star), R(0), //
797 B(LdaConstant), U8(1), //
798 B(Return) //
799 },
800 2,
801 {3.14, 3.14}},
802 {"var a;"
803 REPEAT_256(SPACE, " a = 1.414;")
804 " a = 3.14;",
805 1 * kPointerSize,
806 1,
807 1031,
808 {
809 REPEAT_256(COMMA, //
810 B(LdaConstant), U8(wide_idx++), //
811 B(Star), R(0)), //
812 B(LdaConstantWide), U16(wide_idx), //
813 B(Star), R(0), //
814 B(LdaUndefined), //
815 B(Return), //
816 },
817 257,
818 {REPEAT_256(COMMA, 1.414),
819 3.14}}
820 };
821 for (size_t i = 0; i < arraysize(snippets); i++) {
822 Handle<BytecodeArray> bytecode_array =
823 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
824 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
825 }
826}
827
828
829TEST(StringConstants) {
830 InitializedHandleScope handle_scope;
831 BytecodeGeneratorHelper helper;
832
833 ExpectedSnippet<const char*> snippets[] = {
834 {"return \"This is a string\";",
835 0,
836 1,
837 3,
838 {
839 B(LdaConstant), U8(0), //
840 B(Return) //
841 },
842 1,
843 {"This is a string"}},
844 {"var a = \"First string\"; return \"Second string\";",
845 1 * kPointerSize,
846 1,
847 7,
848 {
849 B(LdaConstant), U8(0), //
850 B(Star), R(0), //
851 B(LdaConstant), U8(1), //
852 B(Return) //
853 },
854 2,
855 {"First string", "Second string"}},
856 {"var a = \"Same string\"; return \"Same string\";",
857 1 * kPointerSize,
858 1,
859 7,
860 {
861 B(LdaConstant), U8(0), //
862 B(Star), R(0), //
863 B(LdaConstant), U8(0), //
864 B(Return) //
865 },
866 1,
867 {"Same string"}}};
868
869 for (size_t i = 0; i < arraysize(snippets); i++) {
870 Handle<BytecodeArray> bytecode_array =
871 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
872 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
873 }
874}
875
876
877TEST(PropertyLoads) {
878 InitializedHandleScope handle_scope;
879 BytecodeGeneratorHelper helper;
880 Zone zone;
881
882 FeedbackVectorSpec feedback_spec(&zone);
883 FeedbackVectorSlot slot1 = feedback_spec.AddLoadICSlot();
884 FeedbackVectorSlot slot2 = feedback_spec.AddLoadICSlot();
885
886 Handle<i::TypeFeedbackVector> vector =
887 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
888
889 // These are a hack used by the LoadICXXXWide tests below.
890 int wide_idx_1 = vector->GetIndex(slot1) - 2;
891 int wide_idx_2 = vector->GetIndex(slot1) - 2;
892 int wide_idx_3 = vector->GetIndex(slot1) - 2;
893 int wide_idx_4 = vector->GetIndex(slot1) - 2;
894
895 ExpectedSnippet<const char*> snippets[] = {
896 {"function f(a) { return a.name; }\nf({name : \"test\"})",
897 1 * kPointerSize,
898 2,
899 9,
900 {
901 B(Ldar), A(1, 2), //
902 B(Star), R(0), //
903 B(LoadICSloppy), R(0), U8(0), U8(vector->GetIndex(slot1)), //
904 B(Return), //
905 },
906 1,
907 {"name"}},
908 {"function f(a) { return a[\"key\"]; }\nf({key : \"test\"})",
909 1 * kPointerSize,
910 2,
911 9,
912 {
913 B(Ldar), A(1, 2), //
914 B(Star), R(0), //
915 B(LoadICSloppy), R(0), U8(0), U8(vector->GetIndex(slot1)), //
916 B(Return) //
917 },
918 1,
919 {"key"}},
920 {"function f(a) { return a[100]; }\nf({100 : \"test\"})",
921 1 * kPointerSize,
922 2,
923 10,
924 {
925 B(Ldar), A(1, 2), //
926 B(Star), R(0), //
927 B(LdaSmi8), U8(100), //
928 B(KeyedLoadICSloppy), R(0), U8(vector->GetIndex(slot1)), //
929 B(Return) //
930 },
931 0},
932 {"function f(a, b) { return a[b]; }\nf({arg : \"test\"}, \"arg\")",
933 1 * kPointerSize,
934 3,
935 10,
936 {
937 B(Ldar), A(1, 3), //
938 B(Star), R(0), //
939 B(Ldar), A(1, 2), //
940 B(KeyedLoadICSloppy), R(0), U8(vector->GetIndex(slot1)), //
941 B(Return) //
942 },
943 0},
944 {"function f(a) { var b = a.name; return a[-124]; }\n"
945 "f({\"-124\" : \"test\", name : 123 })",
946 2 * kPointerSize,
947 2,
948 20,
949 {
950 B(Ldar), A(1, 2), //
951 B(Star), R(1), //
952 B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot1)), //
953 B(Star), R(0), //
954 B(Ldar), A(1, 2), //
955 B(Star), R(1), //
956 B(LdaSmi8), U8(-124), //
957 B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot2)), //
958 B(Return), //
959 },
960 1,
961 {"name"}},
962 {"function f(a) { \"use strict\"; return a.name; }\nf({name : \"test\"})",
963 1 * kPointerSize,
964 2,
965 9,
966 {
967 B(Ldar), A(1, 2), //
968 B(Star), R(0), //
969 B(LoadICStrict), R(0), U8(0), U8(vector->GetIndex(slot1)), //
970 B(Return), //
971 },
972 1,
973 {"name"}},
974 {"function f(a, b) { \"use strict\"; return a[b]; }\n"
975 "f({arg : \"test\"}, \"arg\")",
976 1 * kPointerSize,
977 3,
978 10,
979 {
980 B(Ldar), A(1, 3), //
981 B(Star), R(0), //
982 B(Ldar), A(2, 3), //
983 B(KeyedLoadICStrict), R(0), U8(vector->GetIndex(slot1)), //
984 B(Return), //
985 },
986 0},
987 {"function f(a) {\n"
988 " var b;\n"
989 "b = a.name;"
990 REPEAT_127(SPACE, " b = a.name; ")
991 " return a.name; }\n"
992 "f({name : \"test\"})\n",
993 2 * kPointerSize,
994 2,
995 1291,
996 {
997 B(Ldar), A(1, 2), //
998 B(Star), R(1), //
999 B(LoadICSloppy), R(1), U8(0), U8(wide_idx_1 += 2), //
1000 B(Star), R(0), //
1001 REPEAT_127(COMMA, //
1002 B(Ldar), A(1, 2), //
1003 B(Star), R(1), //
1004 B(LoadICSloppy), R(1), U8(0), //
1005 U8((wide_idx_1 += 2)), //
1006 B(Star), R(0)), //
1007 B(Ldar), A(1, 2), //
1008 B(Star), R(1), //
1009 B(LoadICSloppyWide), R(1), U16(0), U16(wide_idx_1 + 2), //
1010 B(Return), //
1011 },
1012 1,
1013 {"name"}},
1014 {"function f(a) {\n"
1015 " 'use strict'; var b;\n"
1016 " b = a.name;\n"
1017 REPEAT_127(SPACE, " b = a.name; ")
1018 " return a.name; }\n"
1019 "f({name : \"test\"})\n",
1020 2 * kPointerSize,
1021 2,
1022 1291,
1023 {
1024 B(Ldar), A(1, 2), //
1025 B(Star), R(1), //
1026 B(LoadICStrict), R(1), U8(0), U8((wide_idx_2 += 2)), //
1027 B(Star), R(0), //
1028 REPEAT_127(COMMA, //
1029 B(Ldar), A(1, 2), //
1030 B(Star), R(1), //
1031 B(LoadICStrict), R(1), U8(0), //
1032 U8((wide_idx_2 += 2)), //
1033 B(Star), R(0)), //
1034 B(Ldar), A(1, 2), //
1035 B(Star), R(1), //
1036 B(LoadICStrictWide), R(1), U16(0), U16(wide_idx_2 + 2), //
1037 B(Return), //
1038 },
1039 1,
1040 {"name"}},
1041 {"function f(a, b) {\n"
1042 " var c;\n"
1043 " c = a[b];"
1044 REPEAT_127(SPACE, " c = a[b]; ")
1045 " return a[b]; }\n"
1046 "f({name : \"test\"}, \"name\")\n",
1047 2 * kPointerSize,
1048 3,
1049 1419,
1050 {
1051 B(Ldar), A(1, 3), //
1052 B(Star), R(1), //
1053 B(Ldar), A(2, 3), //
1054 B(KeyedLoadICSloppy), R(1), U8((wide_idx_3 += 2)), //
1055 B(Star), R(0), //
1056 REPEAT_127(COMMA, //
1057 B(Ldar), A(1, 3), //
1058 B(Star), R(1), //
1059 B(Ldar), A(2, 3), //
1060 B(KeyedLoadICSloppy), R(1), U8((wide_idx_3 += 2)), //
1061 B(Star), R(0)), //
1062 B(Ldar), A(1, 3), //
1063 B(Star), R(1), //
1064 B(Ldar), A(2, 3), //
1065 B(KeyedLoadICSloppyWide), R(1), U16(wide_idx_3 + 2), //
1066 B(Return), //
1067 }},
1068 {"function f(a, b) {\n"
1069 " 'use strict'; var c;\n"
1070 " c = a[b];"
1071 REPEAT_127(SPACE, " c = a[b]; ")
1072 " return a[b]; }\n"
1073 "f({name : \"test\"}, \"name\")\n",
1074 2 * kPointerSize,
1075 3,
1076 1419,
1077 {
1078 B(Ldar), A(1, 3), //
1079 B(Star), R(1), //
1080 B(Ldar), A(2, 3), //
1081 B(KeyedLoadICStrict), R(1), U8((wide_idx_4 += 2)), //
1082 B(Star), R(0), //
1083 REPEAT_127(COMMA, //
1084 B(Ldar), A(1, 3), //
1085 B(Star), R(1), //
1086 B(Ldar), A(2, 3), //
1087 B(KeyedLoadICStrict), R(1), U8((wide_idx_4 += 2)), //
1088 B(Star), R(0)), //
1089 B(Ldar), A(1, 3), //
1090 B(Star), R(1), //
1091 B(Ldar), A(2, 3), //
1092 B(KeyedLoadICStrictWide), R(1), U16(wide_idx_4 + 2), //
1093 B(Return), //
1094 }},
1095 };
1096 for (size_t i = 0; i < arraysize(snippets); i++) {
1097 Handle<BytecodeArray> bytecode_array =
1098 helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName);
1099 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
1100 }
1101}
1102
1103
1104TEST(PropertyStores) {
1105 InitializedHandleScope handle_scope;
1106 BytecodeGeneratorHelper helper;
1107 Zone zone;
1108
1109 FeedbackVectorSpec feedback_spec(&zone);
1110 FeedbackVectorSlot slot1 = feedback_spec.AddStoreICSlot();
1111 FeedbackVectorSlot slot2 = feedback_spec.AddStoreICSlot();
1112
1113 Handle<i::TypeFeedbackVector> vector =
1114 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
1115
1116 // These are a hack used by the StoreICXXXWide tests below.
1117 int wide_idx_1 = vector->GetIndex(slot1) - 2;
1118 int wide_idx_2 = vector->GetIndex(slot1) - 2;
1119 int wide_idx_3 = vector->GetIndex(slot1) - 2;
1120 int wide_idx_4 = vector->GetIndex(slot1) - 2;
1121
1122 ExpectedSnippet<const char*> snippets[] = {
1123 {"function f(a) { a.name = \"val\"; }\nf({name : \"test\"})",
1124 kPointerSize,
1125 2,
1126 12,
1127 {
1128 B(Ldar), A(1, 2), //
1129 B(Star), R(0), //
1130 B(LdaConstant), U8(0), //
1131 B(StoreICSloppy), R(0), U8(1), U8(vector->GetIndex(slot1)), //
1132 B(LdaUndefined), //
1133 B(Return), //
1134 },
1135 2,
1136 {"val", "name"}},
1137 {"function f(a) { a[\"key\"] = \"val\"; }\nf({key : \"test\"})",
1138 kPointerSize,
1139 2,
1140 12,
1141 {
1142 B(Ldar), A(1, 2), //
1143 B(Star), R(0), //
1144 B(LdaConstant), U8(0), //
1145 B(StoreICSloppy), R(0), U8(1), U8(vector->GetIndex(slot1)), //
1146 B(LdaUndefined), //
1147 B(Return), //
1148 },
1149 2,
1150 {"val", "key"}},
1151 {"function f(a) { a[100] = \"val\"; }\nf({100 : \"test\"})",
1152 2 * kPointerSize,
1153 2,
1154 16,
1155 {
1156 B(Ldar), A(1, 2), //
1157 B(Star), R(0), //
1158 B(LdaSmi8), U8(100), //
1159 B(Star), R(1), //
1160 B(LdaConstant), U8(0), //
1161 B(KeyedStoreICSloppy), R(0), R(1), //
1162 U8(vector->GetIndex(slot1)), //
1163 B(LdaUndefined), //
1164 B(Return), //
1165 },
1166 1,
1167 {"val"}},
1168 {"function f(a, b) { a[b] = \"val\"; }\nf({arg : \"test\"}, \"arg\")",
1169 2 * kPointerSize,
1170 3,
1171 16,
1172 {
1173 B(Ldar), A(1, 3), //
1174 B(Star), R(0), //
1175 B(Ldar), A(2, 3), //
1176 B(Star), R(1), //
1177 B(LdaConstant), U8(0), //
1178 B(KeyedStoreICSloppy), R(0), R(1), //
1179 U8(vector->GetIndex(slot1)), //
1180 B(LdaUndefined), //
1181 B(Return), //
1182 },
1183 1,
1184 {"val"}},
1185 {"function f(a) { a.name = a[-124]; }\n"
1186 "f({\"-124\" : \"test\", name : 123 })",
1187 2 * kPointerSize,
1188 2,
1189 19,
1190 {
1191 B(Ldar), A(1, 2), //
1192 B(Star), R(0), //
1193 B(Ldar), A(1, 2), //
1194 B(Star), R(1), //
1195 B(LdaSmi8), U8(-124), //
1196 B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot1)), //
1197 B(StoreICSloppy), R(0), U8(0), U8(vector->GetIndex(slot2)), //
1198 B(LdaUndefined), //
1199 B(Return), //
1200 },
1201 1,
1202 {"name"}},
1203 {"function f(a) { \"use strict\"; a.name = \"val\"; }\n"
1204 "f({name : \"test\"})",
1205 kPointerSize,
1206 2,
1207 12,
1208 {
1209 B(Ldar), A(1, 2), //
1210 B(Star), R(0), //
1211 B(LdaConstant), U8(0), //
1212 B(StoreICStrict), R(0), U8(1), U8(vector->GetIndex(slot1)), //
1213 B(LdaUndefined), //
1214 B(Return), //
1215 },
1216 2,
1217 {"val", "name"}},
1218 {"function f(a, b) { \"use strict\"; a[b] = \"val\"; }\n"
1219 "f({arg : \"test\"}, \"arg\")",
1220 2 * kPointerSize,
1221 3,
1222 16,
1223 {
1224 B(Ldar), A(1, 3), //
1225 B(Star), R(0), //
1226 B(Ldar), A(2, 3), //
1227 B(Star), R(1), //
1228 B(LdaConstant), U8(0), //
1229 B(KeyedStoreICStrict), R(0), R(1), U8(vector->GetIndex(slot1)), //
1230 B(LdaUndefined), //
1231 B(Return), //
1232 },
1233 1,
1234 {"val"}},
1235 {"function f(a) {\n"
1236 "a.name = 1;"
1237 REPEAT_127(SPACE, " a.name = 1; ")
1238 " a.name = 2; }\n"
1239 "f({name : \"test\"})\n",
1240 kPointerSize,
1241 2,
1242 1294,
1243 {
1244 B(Ldar), A(1, 2), //
1245 B(Star), R(0), //
1246 B(LdaSmi8), U8(1), //
1247 B(StoreICSloppy), R(0), U8(0), U8((wide_idx_1 += 2)), //
1248 REPEAT_127(COMMA, //
1249 B(Ldar), A(1, 2), //
1250 B(Star), R(0), //
1251 B(LdaSmi8), U8(1), //
1252 B(StoreICSloppy), R(0), U8(0), //
1253 U8((wide_idx_1 += 2))), //
1254 B(Ldar), A(1, 2), //
1255 B(Star), R(0), //
1256 B(LdaSmi8), U8(2), //
1257 B(StoreICSloppyWide), R(0), U16(0), U16(wide_idx_1 + 2), //
1258 B(LdaUndefined), //
1259 B(Return), //
1260 },
1261 1,
1262 {"name"}},
1263 {"function f(a) {\n"
1264 " 'use strict';\n"
1265 " a.name = 1;"
1266 REPEAT_127(SPACE, " a.name = 1; ")
1267 " a.name = 2; }\n"
1268 "f({name : \"test\"})\n",
1269 kPointerSize,
1270 2,
1271 1294,
1272 {
1273 B(Ldar), A(1, 2), //
1274 B(Star), R(0), //
1275 B(LdaSmi8), U8(1), //
1276 B(StoreICStrict), R(0), U8(0), U8(wide_idx_2 += 2), //
1277 REPEAT_127(COMMA, //
1278 B(Ldar), A(1, 2), //
1279 B(Star), R(0), //
1280 B(LdaSmi8), U8(1), //
1281 B(StoreICStrict), R(0), U8(0), //
1282 U8((wide_idx_2 += 2))), //
1283 B(Ldar), A(1, 2), //
1284 B(Star), R(0), //
1285 B(LdaSmi8), U8(2), //
1286 B(StoreICStrictWide), R(0), U16(0), U16(wide_idx_2 + 2), //
1287 B(LdaUndefined), //
1288 B(Return), //
1289 },
1290 1,
1291 {"name"}},
1292 {"function f(a, b) {\n"
1293 " a[b] = 1;"
1294 REPEAT_127(SPACE, " a[b] = 1; ")
1295 " a[b] = 2; }\n"
1296 "f({name : \"test\"})\n",
1297 2 * kPointerSize,
1298 3,
1299 1809,
1300 {
1301 B(Ldar), A(1, 3), //
1302 B(Star), R(0), //
1303 B(Ldar), A(2, 3), //
1304 B(Star), R(1), //
1305 B(LdaSmi8), U8(1), //
1306 B(KeyedStoreICSloppy), R(0), R(1), U8(wide_idx_3 += 2), //
1307 REPEAT_127(COMMA, //
1308 B(Ldar), A(1, 3), //
1309 B(Star), R(0), //
1310 B(Ldar), A(2, 3), //
1311 B(Star), R(1), //
1312 B(LdaSmi8), U8(1), //
1313 B(KeyedStoreICSloppy), R(0), R(1), //
1314 U8((wide_idx_3 += 2))), //
1315 B(Ldar), A(1, 3), //
1316 B(Star), R(0), //
1317 B(Ldar), A(2, 3), //
1318 B(Star), R(1), //
1319 B(LdaSmi8), U8(2), //
1320 B(KeyedStoreICSloppyWide), R(0), R(1), U16(wide_idx_3 + 2), //
1321 B(LdaUndefined), //
1322 B(Return), //
1323 }},
1324 {"function f(a, b) {\n"
1325 " 'use strict';\n"
1326 " a[b] = 1;"
1327 REPEAT_127(SPACE, " a[b] = 1; ")
1328 " a[b] = 2; }\n"
1329 "f({name : \"test\"})\n",
1330 2 * kPointerSize,
1331 3,
1332 1809,
1333 {
1334 B(Ldar), A(1, 3), //
1335 B(Star), R(0), //
1336 B(Ldar), A(2, 3), //
1337 B(Star), R(1), //
1338 B(LdaSmi8), U8(1), //
1339 B(KeyedStoreICStrict), R(0), R(1), U8(wide_idx_4 += 2), //
1340 REPEAT_127(COMMA, //
1341 B(Ldar), A(1, 3), //
1342 B(Star), R(0), //
1343 B(Ldar), A(2, 3), //
1344 B(Star), R(1), //
1345 B(LdaSmi8), U8(1), //
1346 B(KeyedStoreICStrict), R(0), R(1), //
1347 U8((wide_idx_4 += 2))), //
1348 B(Ldar), A(1, 3), //
1349 B(Star), R(0), //
1350 B(Ldar), A(2, 3), //
1351 B(Star), R(1), //
1352 B(LdaSmi8), U8(2), //
1353 B(KeyedStoreICStrictWide), R(0), R(1), U16(wide_idx_4 + 2), //
1354 B(LdaUndefined), //
1355 B(Return), //
1356 }}};
1357 for (size_t i = 0; i < arraysize(snippets); i++) {
1358 Handle<BytecodeArray> bytecode_array =
1359 helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName);
1360 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
1361 }
1362}
1363
1364
1365#define FUNC_ARG "new (function Obj() { this.func = function() { return; }})()"
1366
1367
1368TEST(PropertyCall) {
1369 InitializedHandleScope handle_scope;
1370 BytecodeGeneratorHelper helper;
1371 Zone zone;
1372
1373 FeedbackVectorSpec feedback_spec(&zone);
1374 FeedbackVectorSlot slot1 = feedback_spec.AddCallICSlot();
1375 FeedbackVectorSlot slot2 = feedback_spec.AddLoadICSlot();
1376
1377 Handle<i::TypeFeedbackVector> vector =
1378 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
1379
1380 // These are a hack used by the CallWide test below.
1381 int wide_idx = vector->GetIndex(slot1) - 2;
1382
1383 ExpectedSnippet<const char*> snippets[] = {
1384 {"function f(a) { return a.func(); }\nf(" FUNC_ARG ")",
1385 2 * kPointerSize,
1386 2,
1387 16,
1388 {
1389 B(Ldar), A(1, 2), //
1390 B(Star), R(1), //
1391 B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot2)), //
1392 B(Star), R(0), //
1393 B(Call), R(0), R(1), U8(0), U8(vector->GetIndex(slot1)), //
1394 B(Return), //
1395 },
1396 1,
1397 {"func"}},
1398 {"function f(a, b, c) { return a.func(b, c); }\nf(" FUNC_ARG ", 1, 2)",
1399 4 * kPointerSize,
1400 4,
1401 24,
1402 {
1403 B(Ldar), A(1, 4), //
1404 B(Star), R(1), //
1405 B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot2)), //
1406 B(Star), R(0), //
1407 B(Ldar), A(2, 4), //
1408 B(Star), R(2), //
1409 B(Ldar), A(3, 4), //
1410 B(Star), R(3), //
1411 B(Call), R(0), R(1), U8(2), U8(vector->GetIndex(slot1)), //
1412 B(Return) //
1413 },
1414 1,
1415 {"func"}},
1416 {"function f(a, b) { return a.func(b + b, b); }\nf(" FUNC_ARG ", 1)",
1417 4 * kPointerSize,
1418 3,
1419 30,
1420 {
1421 B(Ldar), A(1, 3), //
1422 B(Star), R(1), //
1423 B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot2)), //
1424 B(Star), R(0), //
1425 B(Ldar), A(2, 3), //
1426 B(Star), R(3), //
1427 B(Ldar), A(2, 3), //
1428 B(Add), R(3), //
1429 B(Star), R(2), //
1430 B(Ldar), A(2, 3), //
1431 B(Star), R(3), //
1432 B(Call), R(0), R(1), U8(2), U8(vector->GetIndex(slot1)), //
1433 B(Return), //
1434 },
1435 1,
1436 {"func"}},
1437 {"function f(a) {\n"
1438 " a.func;\n"
1439 REPEAT_127(SPACE, " a.func;\n")
1440 " return a.func(); }\nf(" FUNC_ARG ")",
1441 2 * kPointerSize,
1442 2,
1443 1044,
1444 {
1445 B(Ldar), A(1, 2), //
1446 B(Star), R(0), //
1447 B(LoadICSloppy), R(0), U8(0), U8(wide_idx += 2), //
1448 REPEAT_127(COMMA, //
1449 B(Ldar), A(1, 2), //
1450 B(Star), R(0), //
1451 B(LoadICSloppy), R(0), U8(0), U8((wide_idx += 2))), //
1452 B(Ldar), A(1, 2), //
1453 B(Star), R(1), //
1454 B(LoadICSloppyWide), R(1), U16(0), U16(wide_idx + 4), //
1455 B(Star), R(0), //
1456 B(CallWide), R(0), R(1), U16(0), U16(wide_idx + 2), //
1457 B(Return), //
1458 },
1459 1,
1460 {"func"}},
1461 };
1462 for (size_t i = 0; i < arraysize(snippets); i++) {
1463 Handle<BytecodeArray> bytecode_array =
1464 helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName);
1465 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
1466 }
1467}
1468
1469
1470TEST(LoadGlobal) {
1471 InitializedHandleScope handle_scope;
1472 BytecodeGeneratorHelper helper;
1473 Zone zone;
1474
1475 FeedbackVectorSpec feedback_spec(&zone);
1476 FeedbackVectorSlot slot = feedback_spec.AddLoadICSlot();
1477
1478 Handle<i::TypeFeedbackVector> vector =
1479 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
1480
1481 // These are a hack used by the LdaGlobalXXXWide tests below.
1482 int wide_idx_1 = vector->GetIndex(slot) - 2;
1483 int wide_idx_2 = vector->GetIndex(slot) - 2;
1484
1485 ExpectedSnippet<const char*> snippets[] = {
1486 {"var a = 1;\nfunction f() { return a; }\nf()",
1487 0,
1488 1,
1489 4,
1490 {
1491 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
1492 B(Return) //
1493 },
1494 1,
1495 {"a"}},
1496 {"function t() { }\nfunction f() { return t; }\nf()",
1497 0,
1498 1,
1499 4,
1500 {
1501 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
1502 B(Return) //
1503 },
1504 1,
1505 {"t"}},
1506 {"'use strict'; var a = 1;\nfunction f() { return a; }\nf()",
1507 0,
1508 1,
1509 4,
1510 {
1511 B(LdaGlobalStrict), U8(0), U8(vector->GetIndex(slot)), //
1512 B(Return) //
1513 },
1514 1,
1515 {"a"}},
1516 {"a = 1;\nfunction f() { return a; }\nf()",
1517 0,
1518 1,
1519 4,
1520 {
1521 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
1522 B(Return) //
1523 },
1524 1,
1525 {"a"}},
1526 {"a = 1;"
1527 "function f(b) {\n"
1528 " b.name;\n"
1529 REPEAT_127(SPACE, "b.name; ")
1530 " return a;"
1531 "}\nf({name: 1});",
1532 kPointerSize,
1533 2,
1534 1030,
1535 {
1536 B(Ldar), A(1, 2), //
1537 B(Star), R(0), //
1538 B(LoadICSloppy), R(0), U8(0), U8(wide_idx_1 += 2), //
1539 REPEAT_127(COMMA, //
1540 B(Ldar), A(1, 2), //
1541 B(Star), R(0), //
1542 B(LoadICSloppy), R(0), U8(0), U8(wide_idx_1 += 2)), //
1543 B(LdaGlobalSloppyWide), U16(1), U16(wide_idx_1 + 2), //
1544 B(Return), //
1545 },
1546 2,
1547 {"name", "a"}},
1548 {"a = 1;"
1549 "function f(b) {\n"
1550 " 'use strict';\n"
1551 " b.name\n"
1552 REPEAT_127(SPACE, "b.name; ")
1553 " return a;"
1554 "}\nf({name: 1});",
1555 kPointerSize,
1556 2,
1557 1030,
1558 {
1559 B(Ldar), A(1, 2), //
1560 B(Star), R(0), //
1561 B(LoadICStrict), R(0), U8(0), U8(wide_idx_2 += 2), //
1562 REPEAT_127(COMMA, //
1563 B(Ldar), A(1, 2), //
1564 B(Star), R(0), //
1565 B(LoadICStrict), R(0), U8(0), U8(wide_idx_2 += 2)), //
1566 B(LdaGlobalStrictWide), U16(1), U16(wide_idx_2 + 2), //
1567 B(Return), //
1568 },
1569 2,
1570 {"name", "a"}},
1571 };
1572
1573 for (size_t i = 0; i < arraysize(snippets); i++) {
1574 Handle<BytecodeArray> bytecode_array =
1575 helper.MakeBytecode(snippets[i].code_snippet, "f");
1576 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
1577 }
1578}
1579
1580
1581TEST(StoreGlobal) {
1582 InitializedHandleScope handle_scope;
1583 BytecodeGeneratorHelper helper;
1584 Zone zone;
1585
1586 FeedbackVectorSpec feedback_spec(&zone);
1587 FeedbackVectorSlot slot = feedback_spec.AddStoreICSlot();
1588
1589 Handle<i::TypeFeedbackVector> vector =
1590 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
1591
1592 // These are a hack used by the StaGlobalXXXWide tests below.
1593 int wide_idx_1 = vector->GetIndex(slot) - 2;
1594 int wide_idx_2 = vector->GetIndex(slot) - 2;
1595
1596 ExpectedSnippet<const char*> snippets[] = {
1597 {"var a = 1;\nfunction f() { a = 2; }\nf()",
1598 0,
1599 1,
1600 7,
1601 {
1602 B(LdaSmi8), U8(2), //
1603 B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
1604 B(LdaUndefined), //
1605 B(Return) //
1606 },
1607 1,
1608 {"a"}},
1609 {"var a = \"test\"; function f(b) { a = b; }\nf(\"global\")",
1610 0,
1611 2,
1612 7,
1613 {
1614 B(Ldar), R(helper.kLastParamIndex), //
1615 B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
1616 B(LdaUndefined), //
1617 B(Return) //
1618 },
1619 1,
1620 {"a"}},
1621 {"'use strict'; var a = 1;\nfunction f() { a = 2; }\nf()",
1622 0,
1623 1,
1624 7,
1625 {
1626 B(LdaSmi8), U8(2), //
1627 B(StaGlobalStrict), U8(0), U8(vector->GetIndex(slot)), //
1628 B(LdaUndefined), //
1629 B(Return) //
1630 },
1631 1,
1632 {"a"}},
1633 {"a = 1;\nfunction f() { a = 2; }\nf()",
1634 0,
1635 1,
1636 7,
1637 {
1638 B(LdaSmi8), U8(2), //
1639 B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
1640 B(LdaUndefined), //
1641 B(Return) //
1642 },
1643 1,
1644 {"a"}},
1645 {"a = 1;"
1646 "function f(b) {"
1647 " b.name;\n"
1648 REPEAT_127(SPACE, "b.name; ")
1649 " a = 2; }\n"
1650 "f({name: 1});",
1651 kPointerSize,
1652 2,
1653 1033,
1654 {
1655 B(Ldar), A(1, 2), //
1656 B(Star), R(0), //
1657 B(LoadICSloppy), R(0), U8(0), U8(wide_idx_1 += 2), //
1658 REPEAT_127(COMMA, //
1659 B(Ldar), A(1, 2), //
1660 B(Star), R(0), //
1661 B(LoadICSloppy), R(0), U8(0), U8(wide_idx_1 += 2)), //
1662 B(LdaSmi8), U8(2), //
1663 B(StaGlobalSloppyWide), U16(1), U16(wide_idx_1 + 2), //
1664 B(LdaUndefined), //
1665 B(Return), //
1666 },
1667 2,
1668 {"name", "a"}},
1669 {"a = 1;"
1670 "function f(b) {\n"
1671 " 'use strict';\n"
1672 " b.name;\n"
1673 REPEAT_127(SPACE, "b.name; ")
1674 " a = 2; }\n"
1675 "f({name: 1});",
1676 kPointerSize,
1677 2,
1678 1033,
1679 {
1680 B(Ldar), A(1, 2), //
1681 B(Star), R(0), //
1682 B(LoadICStrict), R(0), U8(0), U8(wide_idx_2 += 2), //
1683 REPEAT_127(COMMA, //
1684 B(Ldar), A(1, 2), //
1685 B(Star), R(0), //
1686 B(LoadICStrict), R(0), U8(0), U8(wide_idx_2 += 2)), //
1687 B(LdaSmi8), U8(2), //
1688 B(StaGlobalStrictWide), U16(1), U16(wide_idx_2 + 2), //
1689 B(LdaUndefined), //
1690 B(Return), //
1691 },
1692 2,
1693 {"name", "a"}},
1694 };
1695
1696 for (size_t i = 0; i < arraysize(snippets); i++) {
1697 Handle<BytecodeArray> bytecode_array =
1698 helper.MakeBytecode(snippets[i].code_snippet, "f");
1699 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
1700 }
1701}
1702
1703
1704TEST(CallGlobal) {
1705 InitializedHandleScope handle_scope;
1706 BytecodeGeneratorHelper helper;
1707 Zone zone;
1708
1709 FeedbackVectorSpec feedback_spec(&zone);
1710 FeedbackVectorSlot slot1 = feedback_spec.AddCallICSlot();
1711 FeedbackVectorSlot slot2 = feedback_spec.AddLoadICSlot();
1712
1713 Handle<i::TypeFeedbackVector> vector =
1714 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
1715
1716 ExpectedSnippet<const char*> snippets[] = {
1717 {"function t() { }\nfunction f() { return t(); }\nf()",
1718 2 * kPointerSize,
1719 1,
1720 14,
1721 {
1722 B(LdaUndefined), //
1723 B(Star), R(1), //
1724 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
1725 B(Star), R(0), //
1726 B(Call), R(0), R(1), U8(0), U8(vector->GetIndex(slot1)), //
1727 B(Return) //
1728 },
1729 1,
1730 {"t"}},
1731 {"function t(a, b, c) { }\nfunction f() { return t(1, 2, 3); }\nf()",
1732 5 * kPointerSize,
1733 1,
1734 26,
1735 {
1736 B(LdaUndefined), //
1737 B(Star), R(1), //
1738 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
1739 B(Star), R(0), //
1740 B(LdaSmi8), U8(1), //
1741 B(Star), R(2), //
1742 B(LdaSmi8), U8(2), //
1743 B(Star), R(3), //
1744 B(LdaSmi8), U8(3), //
1745 B(Star), R(4), //
1746 B(Call), R(0), R(1), U8(3), U8(vector->GetIndex(slot1)), //
1747 B(Return) //
1748 },
1749 1,
1750 {"t"}},
1751 };
1752
1753 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
1754 for (size_t i = 0; i < num_snippets; i++) {
1755 Handle<BytecodeArray> bytecode_array =
1756 helper.MakeBytecode(snippets[i].code_snippet, "f");
1757 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
1758 }
1759}
1760
1761
1762TEST(CallRuntime) {
1763 InitializedHandleScope handle_scope;
1764 BytecodeGeneratorHelper helper;
1765
1766 ExpectedSnippet<InstanceType> snippets[] = {
1767 {
1768 "function f() { %TheHole() }\nf()",
1769 0,
1770 1,
1771 7,
1772 {
1773 B(CallRuntime), U16(Runtime::kTheHole), R(0), U8(0), //
1774 B(LdaUndefined), //
1775 B(Return) //
1776 },
1777 },
1778 {
1779 "function f(a) { return %IsArray(a) }\nf(undefined)",
1780 1 * kPointerSize,
1781 2,
1782 10,
1783 {
1784 B(Ldar), A(1, 2), //
1785 B(Star), R(0), //
1786 B(CallRuntime), U16(Runtime::kIsArray), R(0), U8(1), //
1787 B(Return) //
1788 },
1789 },
1790 {
1791 "function f() { return %Add(1, 2) }\nf()",
1792 2 * kPointerSize,
1793 1,
1794 14,
1795 {
1796 B(LdaSmi8), U8(1), //
1797 B(Star), R(0), //
1798 B(LdaSmi8), U8(2), //
1799 B(Star), R(1), //
1800 B(CallRuntime), U16(Runtime::kAdd), R(0), U8(2), //
1801 B(Return) //
1802 },
1803 },
1804 {
1805 "function f() { return %spread_iterable([1]) }\nf()",
1806 2 * kPointerSize,
1807 1,
1808 15,
1809 {
1810 B(LdaUndefined), //
1811 B(Star), R(0), //
1812 B(CreateArrayLiteral), U8(0), U8(0), U8(3), //
1813 B(Star), R(1), //
1814 B(CallJSRuntime), U16(Context::SPREAD_ITERABLE_INDEX), R(0), //
1815 U8(1), //
1816 B(Return), //
1817 },
1818 1,
1819 {InstanceType::FIXED_ARRAY_TYPE},
1820 },
1821 };
1822
1823 for (size_t i = 0; i < arraysize(snippets); i++) {
1824 Handle<BytecodeArray> bytecode_array =
1825 helper.MakeBytecode(snippets[i].code_snippet, "f");
1826 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
1827 }
1828}
1829
1830
1831TEST(IfConditions) {
1832 InitializedHandleScope handle_scope;
1833 BytecodeGeneratorHelper helper;
1834
1835 Handle<Object> unused = helper.factory()->undefined_value();
1836
1837 ExpectedSnippet<Handle<Object>> snippets[] = {
1838 {"function f() { if (0) { return 1; } else { return -1; } } f()",
1839 0,
1840 1,
1841 3,
1842 {
1843 B(LdaSmi8), U8(-1), //
1844 B(Return), //
1845 },
1846 0,
1847 {unused, unused, unused, unused, unused, unused}},
1848 {"function f() { if ('lucky') { return 1; } else { return -1; } } f();",
1849 0,
1850 1,
1851 3,
1852 {
1853 B(LdaSmi8), U8(1), //
1854 B(Return), //
1855 },
1856 0,
1857 {unused, unused, unused, unused, unused, unused}},
1858 {"function f() { if (false) { return 1; } else { return -1; } } f();",
1859 0,
1860 1,
1861 3,
1862 {
1863 B(LdaSmi8), U8(-1), //
1864 B(Return), //
1865 },
1866 0,
1867 {unused, unused, unused, unused, unused, unused}},
1868 {"function f() { if (false) { return 1; } } f();",
1869 0,
1870 1,
1871 2,
1872 {
1873 B(LdaUndefined), //
1874 B(Return), //
1875 },
1876 0,
1877 {unused, unused, unused, unused, unused, unused}},
1878 {"function f() { var a = 1; if (a) { a += 1; } else { return 2; } } f();",
1879 2 * kPointerSize,
1880 1,
1881 23,
1882 {
1883 B(LdaSmi8), U8(1), //
1884 B(Star), R(0), //
1885 B(JumpIfToBooleanFalse), U8(14), //
1886 B(Ldar), R(0), //
1887 B(Star), R(1), //
1888 B(LdaSmi8), U8(1), //
1889 B(Add), R(1), //
1890 B(Star), R(0), //
1891 B(Jump), U8(5), //
1892 B(LdaSmi8), U8(2), //
1893 B(Return), //
1894 B(LdaUndefined), //
1895 B(Return), //
1896 },
1897 0,
1898 {unused, unused, unused, unused, unused, unused}},
1899 {"function f(a) { if (a <= 0) { return 200; } else { return -200; } }"
1900 "f(99);",
1901 kPointerSize,
1902 2,
1903 17,
1904 {
1905 B(Ldar), A(1, 2), //
1906 B(Star), R(0), //
1907 B(LdaZero), //
1908 B(TestLessThanOrEqual), R(0), //
1909 B(JumpIfFalse), U8(5), //
1910 B(LdaConstant), U8(0), //
1911 B(Return), //
1912 B(LdaConstant), U8(1), //
1913 B(Return), //
1914 B(LdaUndefined), //
1915 B(Return), //
1916 },
1917 2,
1918 {helper.factory()->NewNumberFromInt(200),
1919 helper.factory()->NewNumberFromInt(-200), unused, unused, unused,
1920 unused}},
1921 {"function f(a, b) { if (a in b) { return 200; } }"
1922 "f('prop', { prop: 'yes'});",
1923 kPointerSize,
1924 3,
1925 15,
1926 {
1927 B(Ldar), A(1, 3), //
1928 B(Star), R(0), //
1929 B(Ldar), A(2, 3), //
1930 B(TestIn), R(0), //
1931 B(JumpIfFalse), U8(5), //
1932 B(LdaConstant), U8(0), //
1933 B(Return), //
1934 B(LdaUndefined), //
1935 B(Return), //
1936 },
1937 1,
1938 {helper.factory()->NewNumberFromInt(200), unused, unused, unused, unused,
1939 unused}},
1940 {"function f(z) { var a = 0; var b = 0; if (a === 0.01) { "
1941 REPEAT_64(SPACE, "b = a; a = b; ")
1942 " return 200; } else { return -200; } } f(0.001)",
1943 3 * kPointerSize,
1944 2,
1945 282,
1946 {
1947 B(LdaZero), //
1948 B(Star), R(0), //
1949 B(LdaZero), //
1950 B(Star), R(1), //
1951 B(Ldar), R(0), //
1952 B(Star), R(2), //
1953 B(LdaConstant), U8(0), //
1954 B(TestEqualStrict), R(2), //
1955 B(JumpIfFalseConstant), U8(2), //
1956 B(Ldar), R(0), //
1957 REPEAT_64(COMMA, //
1958 B(Star), R(1), //
1959 B(Star), R(0)), //
1960 B(LdaConstant), U8(1), //
1961 B(Return), //
1962 B(LdaConstant), U8(3), //
1963 B(Return), //
1964 B(LdaUndefined), //
1965 B(Return)}, //
1966 4,
1967 {helper.factory()->NewHeapNumber(0.01),
1968 helper.factory()->NewNumberFromInt(200),
1969 helper.factory()->NewNumberFromInt(263),
1970 helper.factory()->NewNumberFromInt(-200), unused, unused}},
1971 {"function f() { var a = 0; var b = 0; if (a) { "
1972 REPEAT_64(SPACE, "b = a; a = b; ")
1973 " return 200; } else { return -200; } } f()",
1974 2 * kPointerSize,
1975 1,
1976 276,
1977 {
1978 B(LdaZero), //
1979 B(Star), R(0), //
1980 B(LdaZero), //
1981 B(Star), R(1), //
1982 B(Ldar), R(0), //
1983 B(JumpIfToBooleanFalseConstant), U8(1), //
1984 B(Ldar), R(0), //
1985 REPEAT_64(COMMA, //
1986 B(Star), R(1), //
1987 B(Star), R(0)), //
1988 B(LdaConstant), U8(0), //
1989 B(Return), //
1990 B(LdaConstant), U8(2), //
1991 B(Return), //
1992 B(LdaUndefined), //
1993 B(Return)}, //
1994 3,
1995 {helper.factory()->NewNumberFromInt(200),
1996 helper.factory()->NewNumberFromInt(263),
1997 helper.factory()->NewNumberFromInt(-200), unused, unused, unused}},
1998
1999 {"function f(a, b) {\n"
2000 " if (a == b) { return 1; }\n"
2001 " if (a === b) { return 1; }\n"
2002 " if (a < b) { return 1; }\n"
2003 " if (a > b) { return 1; }\n"
2004 " if (a <= b) { return 1; }\n"
2005 " if (a >= b) { return 1; }\n"
2006 " if (a in b) { return 1; }\n"
2007 " if (a instanceof b) { return 1; }\n"
2008 " return 0;\n"
2009 "} f(1, 1);",
2010 kPointerSize,
2011 3,
2012 106,
2013 {
2014#define IF_CONDITION_RETURN(condition) \
2015 B(Ldar), A(1, 3), \
2016 B(Star), R(0), \
2017 B(Ldar), A(2, 3), \
2018 B(condition), R(0), \
2019 B(JumpIfFalse), U8(5), \
2020 B(LdaSmi8), U8(1), \
2021 B(Return),
2022 IF_CONDITION_RETURN(TestEqual) //
2023 IF_CONDITION_RETURN(TestEqualStrict) //
2024 IF_CONDITION_RETURN(TestLessThan) //
2025 IF_CONDITION_RETURN(TestGreaterThan) //
2026 IF_CONDITION_RETURN(TestLessThanOrEqual) //
2027 IF_CONDITION_RETURN(TestGreaterThanOrEqual) //
2028 IF_CONDITION_RETURN(TestIn) //
2029 IF_CONDITION_RETURN(TestInstanceOf) //
2030 B(LdaZero), //
2031 B(Return)}, //
2032#undef IF_CONDITION_RETURN
2033 0,
2034 {unused, unused, unused, unused, unused, unused}},
2035 {"function f() {"
2036 " var a = 0;"
2037 " if (a) {"
2038 " return 20;"
2039 "} else {"
2040 " return -20;}"
2041 "};"
2042 "f();",
2043 1 * kPointerSize,
2044 1,
2045 13,
2046 {
2047 B(LdaZero), //
2048 B(Star), R(0), //
2049 B(JumpIfToBooleanFalse), U8(5), //
2050 B(LdaSmi8), U8(20), //
2051 B(Return), //
2052 B(LdaSmi8), U8(-20), //
2053 B(Return), //
2054 B(LdaUndefined), //
2055 B(Return)
2056 },
2057 0,
2058 {unused, unused, unused, unused, unused, unused}}};
2059
2060 for (size_t i = 0; i < arraysize(snippets); i++) {
2061 Handle<BytecodeArray> bytecode_array =
2062 helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName);
2063 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
2064 }
2065}
2066
2067
2068TEST(DeclareGlobals) {
2069 InitializedHandleScope handle_scope;
2070 BytecodeGeneratorHelper helper;
2071 Zone zone;
2072
2073 // Create different feedback vector specs to be precise on slot numbering.
2074 FeedbackVectorSpec feedback_spec_stores(&zone);
2075 FeedbackVectorSlot store_slot_1 = feedback_spec_stores.AddStoreICSlot();
2076 FeedbackVectorSlot store_slot_2 = feedback_spec_stores.AddStoreICSlot();
2077 USE(store_slot_1);
2078
2079 Handle<i::TypeFeedbackVector> store_vector =
2080 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec_stores);
2081
2082 FeedbackVectorSpec feedback_spec_loads(&zone);
2083 FeedbackVectorSlot load_slot_1 = feedback_spec_loads.AddLoadICSlot();
2084 FeedbackVectorSlot call_slot_1 = feedback_spec_loads.AddCallICSlot();
2085
2086 Handle<i::TypeFeedbackVector> load_vector =
2087 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec_loads);
2088
2089 ExpectedSnippet<InstanceType> snippets[] = {
2090 {"var a = 1;",
2091 4 * kPointerSize,
2092 1,
2093 30,
2094 {
2095 B(LdaConstant), U8(0), //
2096 B(Star), R(1), //
2097 B(LdaZero), //
2098 B(Star), R(2), //
2099 B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2), //
2100 B(LdaConstant), U8(1), //
2101 B(Star), R(1), //
2102 B(LdaZero), //
2103 B(Star), R(2), //
2104 B(LdaSmi8), U8(1), //
2105 B(Star), R(3), //
2106 B(CallRuntime), U16(Runtime::kInitializeVarGlobal), R(1), U8(3), //
2107 B(LdaUndefined), //
2108 B(Return) //
2109 },
2110 2,
2111 {InstanceType::FIXED_ARRAY_TYPE,
2112 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
2113 {"function f() {}",
2114 2 * kPointerSize,
2115 1,
2116 14,
2117 {
2118 B(LdaConstant), U8(0), //
2119 B(Star), R(0), //
2120 B(LdaZero), //
2121 B(Star), R(1), //
2122 B(CallRuntime), U16(Runtime::kDeclareGlobals), R(0), U8(2), //
2123 B(LdaUndefined), //
2124 B(Return) //
2125 },
2126 1,
2127 {InstanceType::FIXED_ARRAY_TYPE}},
2128 {"var a = 1;\na=2;",
2129 4 * kPointerSize,
2130 1,
2131 36,
2132 {
2133 B(LdaConstant), U8(0), //
2134 B(Star), R(1), //
2135 B(LdaZero), //
2136 B(Star), R(2), //
2137 B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2), //
2138 B(LdaConstant), U8(1), //
2139 B(Star), R(1), //
2140 B(LdaZero), //
2141 B(Star), R(2), //
2142 B(LdaSmi8), U8(1), //
2143 B(Star), R(3), //
2144 B(CallRuntime), U16(Runtime::kInitializeVarGlobal), R(1), U8(3), //
2145 B(LdaSmi8), U8(2), //
2146 B(StaGlobalSloppy), U8(1), //
2147 U8(store_vector->GetIndex(store_slot_2)), //
2148 B(Star), R(0), //
2149 B(Return) //
2150 },
2151 2,
2152 {InstanceType::FIXED_ARRAY_TYPE,
2153 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
2154 {"function f() {}\nf();",
2155 3 * kPointerSize,
2156 1,
2157 28,
2158 {
2159 B(LdaConstant), U8(0), //
2160 B(Star), R(1), //
2161 B(LdaZero), //
2162 B(Star), R(2), //
2163 B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2), //
2164 B(LdaUndefined), //
2165 B(Star), R(2), //
2166 B(LdaGlobalSloppy), U8(1), //
2167 U8(load_vector->GetIndex(load_slot_1)), //
2168 B(Star), R(1), //
2169 B(Call), R(1), R(2), U8(0), //
2170 U8(load_vector->GetIndex(call_slot_1)), //
2171 B(Star), R(0), //
2172 B(Return) //
2173 },
2174 2,
2175 {InstanceType::FIXED_ARRAY_TYPE,
2176 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
2177 };
2178
2179 for (size_t i = 0; i < arraysize(snippets); i++) {
2180 Handle<BytecodeArray> bytecode_array =
2181 helper.MakeTopLevelBytecode(snippets[i].code_snippet);
2182 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
2183 }
2184}
2185
2186
2187TEST(BreakableBlocks) {
2188 InitializedHandleScope handle_scope;
2189 BytecodeGeneratorHelper helper;
2190
2191 ExpectedSnippet<int> snippets[] = {
2192 {"var x = 0;\n"
2193 "label: {\n"
2194 " x = x + 1;\n"
2195 " break label;\n"
2196 " x = x + 1;\n"
2197 "}\n"
2198 "return x;",
2199 2 * kPointerSize,
2200 1,
2201 16,
2202 {
2203 B(LdaZero), //
2204 B(Star), R(0), //
2205 B(Star), R(1), //
2206 B(LdaSmi8), U8(1), //
2207 B(Add), R(1), //
2208 B(Star), R(0), //
2209 B(Jump), U8(2), //
2210 B(Ldar), R(0), //
2211 B(Return) //
2212 }},
2213 {"var sum = 0;\n"
2214 "outer: {\n"
2215 " for (var x = 0; x < 10; ++x) {\n"
2216 " for (var y = 0; y < 3; ++y) {\n"
2217 " ++sum;\n"
2218 " if (x + y == 12) { break outer; }\n"
2219 " }\n"
2220 " }\n"
2221 "}\n"
2222 "return sum;",
2223 5 * kPointerSize,
2224 1,
2225 72,
2226 {
2227 B(LdaZero), //
2228 B(Star), R(0), //
2229 B(LdaZero), //
2230 B(Star), R(1), //
2231 B(Ldar), R(1), //
2232 B(Star), R(3), //
2233 B(LdaSmi8), U8(10), //
2234 B(TestLessThan), R(3), //
2235 B(JumpIfFalse), U8(55), //
2236 B(LdaZero), //
2237 B(Star), R(2), //
2238 B(Ldar), R(2), //
2239 B(Star), R(3), //
2240 B(LdaSmi8), U8(3), //
2241 B(TestLessThan), R(3), //
2242 B(JumpIfFalse), U8(34), //
2243 B(Ldar), R(0), //
2244 B(ToNumber), //
2245 B(Inc), //
2246 B(Star), R(0), //
2247 B(Ldar), R(1), //
2248 B(Star), R(3), //
2249 B(Ldar), R(2), //
2250 B(Add), R(3), //
2251 B(Star), R(4), //
2252 B(LdaSmi8), U8(12), //
2253 B(TestEqual), R(4), //
2254 B(JumpIfFalse), U8(4), //
2255 B(Jump), U8(18), //
2256 B(Ldar), R(2), //
2257 B(ToNumber), //
2258 B(Inc), //
2259 B(Star), R(2), //
2260 B(Jump), U8(-40), //
2261 B(Ldar), R(1), //
2262 B(ToNumber), //
2263 B(Inc), //
2264 B(Star), R(1), //
2265 B(Jump), U8(-61), //
2266 B(Ldar), R(0), //
2267 B(Return), //
2268 }},
2269 };
2270
2271 for (size_t i = 0; i < arraysize(snippets); i++) {
2272 Handle<BytecodeArray> bytecode_array =
2273 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
2274 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
2275 }
2276}
2277
2278
2279TEST(BasicLoops) {
2280 InitializedHandleScope handle_scope;
2281 BytecodeGeneratorHelper helper;
2282
2283 ExpectedSnippet<int> snippets[] = {
2284 {"var x = 0;\n"
2285 "while (false) { x = 99; break; continue; }\n"
2286 "return x;",
2287 1 * kPointerSize,
2288 1,
2289 4,
2290 {
2291 B(LdaZero), //
2292 B(Star), R(0), //
2293 B(Return) //
2294 }},
2295 {"var x = 0;"
2296 "while (false) {"
2297 " x = x + 1;"
2298 "};"
2299 "return x;",
2300 1 * kPointerSize,
2301 1,
2302 4,
2303 {
2304 B(LdaZero), //
2305 B(Star), R(0), //
2306 B(Return), //
2307 },
2308 0},
2309 {"var x = 0;"
2310 "var y = 1;"
2311 "while (x < 10) {"
2312 " y = y * 12;"
2313 " x = x + 1;"
2314 " if (x == 3) continue;"
2315 " if (x == 4) break;"
2316 "}"
2317 "return y;",
2318 3 * kPointerSize,
2319 1,
2320 64,
2321 {
2322 B(LdaZero), //
2323 B(Star), R(0), //
2324 B(LdaSmi8), U8(1), //
2325 B(Star), R(1), //
2326 B(Ldar), R(0), //
2327 B(Star), R(2), //
2328 B(LdaSmi8), U8(10), //
2329 B(TestLessThan), R(2), //
2330 B(JumpIfFalse), U8(46), //
2331 B(Ldar), R(1), //
2332 B(Star), R(2), //
2333 B(LdaSmi8), U8(12), //
2334 B(Mul), R(2), //
2335 B(Star), R(1), //
2336 B(Ldar), R(0), //
2337 B(Star), R(2), //
2338 B(LdaSmi8), U8(1), //
2339 B(Add), R(2), //
2340 B(Star), R(0), //
2341 B(Star), R(2), //
2342 B(LdaSmi8), U8(3), //
2343 B(TestEqual), R(2), //
2344 B(JumpIfFalse), U8(4), //
2345 B(Jump), U8(-38), //
2346 B(Ldar), R(0), //
2347 B(Star), R(2), //
2348 B(LdaSmi8), U8(4), //
2349 B(TestEqual), R(2), //
2350 B(JumpIfFalse), U8(4), //
2351 B(Jump), U8(4), //
2352 B(Jump), U8(-52), //
2353 B(Ldar), R(1), //
2354 B(Return), //
2355 },
2356 0},
2357 {"var i = 0;"
2358 "while (true) {"
2359 " if (i < 0) continue;"
2360 " if (i == 3) break;"
2361 " if (i == 4) break;"
2362 " if (i == 10) continue;"
2363 " if (i == 5) break;"
2364 " i = i + 1;"
2365 "}"
2366 "return i;",
2367 2 * kPointerSize,
2368 1,
2369 77,
2370 {
2371 B(LdaZero), //
2372 B(Star), R(0), //
2373 B(Ldar), R(0), //
2374 B(Star), R(1), //
2375 B(LdaZero), //
2376 B(TestLessThan), R(1), //
2377 B(JumpIfFalse), U8(4), //
2378 B(Jump), U8(-9), //
2379 B(Ldar), R(0), //
2380 B(Star), R(1), //
2381 B(LdaSmi8), U8(3), //
2382 B(TestEqual), R(1), //
2383 B(JumpIfFalse), U8(4), //
2384 B(Jump), U8(50), //
2385 B(Ldar), R(0), //
2386 B(Star), R(1), //
2387 B(LdaSmi8), U8(4), //
2388 B(TestEqual), R(1), //
2389 B(JumpIfFalse), U8(4), //
2390 B(Jump), U8(38), //
2391 B(Ldar), R(0), //
2392 B(Star), R(1), //
2393 B(LdaSmi8), U8(10), //
2394 B(TestEqual), R(1), //
2395 B(JumpIfFalse), U8(4), //
2396 B(Jump), U8(-45), //
2397 B(Ldar), R(0), //
2398 B(Star), R(1), //
2399 B(LdaSmi8), U8(5), //
2400 B(TestEqual), R(1), //
2401 B(JumpIfFalse), U8(4), //
2402 B(Jump), U8(14), //
2403 B(Ldar), R(0), //
2404 B(Star), R(1), //
2405 B(LdaSmi8), U8(1), //
2406 B(Add), R(1), //
2407 B(Star), R(0), //
2408 B(Jump), U8(-69), //
2409 B(Ldar), R(0), //
2410 B(Return), //
2411 },
2412 0},
2413 {"var i = 0;"
2414 "while (true) {"
2415 " while (i < 3) {"
2416 " if (i == 2) break;"
2417 " i = i + 1;"
2418 " }"
2419 " i = i + 1;"
2420 " break;"
2421 "}"
2422 "return i;",
2423 2 * kPointerSize,
2424 1,
2425 54,
2426 {
2427 B(LdaZero), //
2428 B(Star), R(0), //
2429 B(Ldar), R(0), //
2430 B(Star), R(1), //
2431 B(LdaSmi8), U8(3), //
2432 B(TestLessThan), R(1), //
2433 B(JumpIfFalse), U8(26), //
2434 B(Ldar), R(0), //
2435 B(Star), R(1), //
2436 B(LdaSmi8), U8(2), //
2437 B(TestEqual), R(1), //
2438 B(JumpIfFalse), U8(4), //
2439 B(Jump), U8(14), //
2440 B(Ldar), R(0), //
2441 B(Star), R(1), //
2442 B(LdaSmi8), U8(1), //
2443 B(Add), R(1), //
2444 B(Star), R(0), //
2445 B(Jump), U8(-32), //
2446 B(Ldar), R(0), //
2447 B(Star), R(1), //
2448 B(LdaSmi8), U8(1), //
2449 B(Add), R(1), //
2450 B(Star), R(0), //
2451 B(Jump), U8(4), //
2452 B(Jump), U8(-46), //
2453 B(Ldar), R(0), //
2454 B(Return), //
2455 },
2456 0},
2457 {"var x = 10;"
2458 "var y = 1;"
2459 "while (x) {"
2460 " y = y * 12;"
2461 " x = x - 1;"
2462 "}"
2463 "return y;",
2464 3 * kPointerSize,
2465 1,
2466 37,
2467 {
2468 B(LdaSmi8), U8(10), //
2469 B(Star), R(0), //
2470 B(LdaSmi8), U8(1), //
2471 B(Star), R(1), //
2472 B(Ldar), R(0), //
2473 B(JumpIfToBooleanFalse), U8(24), //
2474 B(Ldar), R(1), //
2475 B(Star), R(2), //
2476 B(LdaSmi8), U8(12), //
2477 B(Mul), R(2), //
2478 B(Star), R(1), //
2479 B(Ldar), R(0), //
2480 B(Star), R(2), //
2481 B(LdaSmi8), U8(1), //
2482 B(Sub), R(2), //
2483 B(Star), R(0), //
2484 B(Jump), U8(-24), //
2485 B(Ldar), R(1), //
2486 B(Return), //
2487 },
2488 0},
2489 {"var x = 0; var y = 1;"
2490 "do {"
2491 " y = y * 10;"
2492 " if (x == 5) break;"
2493 " if (x == 6) continue;"
2494 " x = x + 1;"
2495 "} while (x < 10);"
2496 "return y;",
2497 3 * kPointerSize,
2498 1,
2499 64,
2500 {
2501 B(LdaZero), //
2502 B(Star), R(0), //
2503 B(LdaSmi8), U8(1), //
2504 B(Star), R(1), //
2505 B(Ldar), R(1), //
2506 B(Star), R(2), //
2507 B(LdaSmi8), U8(10), //
2508 B(Mul), R(2), //
2509 B(Star), R(1), //
2510 B(Ldar), R(0), //
2511 B(Star), R(2), //
2512 B(LdaSmi8), U8(5), //
2513 B(TestEqual), R(2), //
2514 B(JumpIfFalse), U8(4), //
2515 B(Jump), U8(34), //
2516 B(Ldar), R(0), //
2517 B(Star), R(2), //
2518 B(LdaSmi8), U8(6), //
2519 B(TestEqual), R(2), //
2520 B(JumpIfFalse), U8(4), //
2521 B(Jump), U8(12), //
2522 B(Ldar), R(0), //
2523 B(Star), R(2), //
2524 B(LdaSmi8), U8(1), //
2525 B(Add), R(2), //
2526 B(Star), R(0), //
2527 B(Ldar), R(0), //
2528 B(Star), R(2), //
2529 B(LdaSmi8), U8(10), //
2530 B(TestLessThan), R(2), //
2531 B(JumpIfTrue), U8(-52), //
2532 B(Ldar), R(1), //
2533 B(Return), //
2534 },
2535 0},
2536 {"var x = 10;"
2537 "var y = 1;"
2538 "do {"
2539 " y = y * 12;"
2540 " x = x - 1;"
2541 "} while (x);"
2542 "return y;",
2543 3 * kPointerSize,
2544 1,
2545 35,
2546 {
2547 B(LdaSmi8), U8(10), //
2548 B(Star), R(0), //
2549 B(LdaSmi8), U8(1), //
2550 B(Star), R(1), //
2551 B(Ldar), R(1), //
2552 B(Star), R(2), //
2553 B(LdaSmi8), U8(12), //
2554 B(Mul), R(2), //
2555 B(Star), R(1), //
2556 B(Ldar), R(0), //
2557 B(Star), R(2), //
2558 B(LdaSmi8), U8(1), //
2559 B(Sub), R(2), //
2560 B(Star), R(0), //
2561 B(Ldar), R(0), //
2562 B(JumpIfToBooleanTrue), U8(-22), //
2563 B(Ldar), R(1), //
2564 B(Return), //
2565 },
2566 0},
2567 {"var x = 0; var y = 1;"
2568 "do {"
2569 " y = y * 10;"
2570 " if (x == 5) break;"
2571 " x = x + 1;"
2572 " if (x == 6) continue;"
2573 "} while (false);"
2574 "return y;",
2575 3 * kPointerSize,
2576 1,
2577 52,
2578 {
2579 B(LdaZero), //
2580 B(Star), R(0), //
2581 B(LdaSmi8), U8(1), //
2582 B(Star), R(1), //
2583 B(Ldar), R(1), //
2584 B(Star), R(2), //
2585 B(LdaSmi8), U8(10), //
2586 B(Mul), R(2), //
2587 B(Star), R(1), //
2588 B(Ldar), R(0), //
2589 B(Star), R(2), //
2590 B(LdaSmi8), U8(5), //
2591 B(TestEqual), R(2), //
2592 B(JumpIfFalse), U8(4), //
2593 B(Jump), U8(22), //
2594 B(Ldar), R(0), //
2595 B(Star), R(2), //
2596 B(LdaSmi8), U8(1), //
2597 B(Add), R(2), //
2598 B(Star), R(0), //
2599 B(Star), R(2), //
2600 B(LdaSmi8), U8(6), //
2601 B(TestEqual), R(2), //
2602 B(JumpIfFalse), U8(4), //
2603 B(Jump), U8(2), //
2604 B(Ldar), R(1), //
2605 B(Return), //
2606 },
2607 0},
2608 {"var x = 0; var y = 1;"
2609 "do {"
2610 " y = y * 10;"
2611 " if (x == 5) break;"
2612 " x = x + 1;"
2613 " if (x == 6) continue;"
2614 "} while (true);"
2615 "return y;",
2616 3 * kPointerSize,
2617 1,
2618 54,
2619 {
2620 B(LdaZero), //
2621 B(Star), R(0), //
2622 B(LdaSmi8), U8(1), //
2623 B(Star), R(1), //
2624 B(Ldar), R(1), //
2625 B(Star), R(2), //
2626 B(LdaSmi8), U8(10), //
2627 B(Mul), R(2), //
2628 B(Star), R(1), //
2629 B(Ldar), R(0), //
2630 B(Star), R(2), //
2631 B(LdaSmi8), U8(5), //
2632 B(TestEqual), R(2), //
2633 B(JumpIfFalse), U8(4), //
2634 B(Jump), U8(24), //
2635 B(Ldar), R(0), //
2636 B(Star), R(2), //
2637 B(LdaSmi8), U8(1), //
2638 B(Add), R(2), //
2639 B(Star), R(0), //
2640 B(Star), R(2), //
2641 B(LdaSmi8), U8(6), //
2642 B(TestEqual), R(2), //
2643 B(JumpIfFalse), U8(4), //
2644 B(Jump), U8(-40), //
2645 B(Jump), U8(-42), //
2646 B(Ldar), R(1), //
2647 B(Return), //
2648 },
2649 0},
2650 {"var x = 0; "
2651 "for (;;) {"
2652 " if (x == 1) break;"
2653 " if (x == 2) continue;"
2654 " x = x + 1;"
2655 "}",
2656 2 * kPointerSize,
2657 1,
2658 41,
2659 {
2660 B(LdaZero), //
2661 B(Star), R(0), //
2662 B(Ldar), R(0), //
2663 B(Star), R(1), //
2664 B(LdaSmi8), U8(1), //
2665 B(TestEqual), R(1), //
2666 B(JumpIfFalse), U8(4), //
2667 B(Jump), U8(26), //
2668 B(Ldar), R(0), //
2669 B(Star), R(1), //
2670 B(LdaSmi8), U8(2), //
2671 B(TestEqual), R(1), //
2672 B(JumpIfFalse), U8(4), //
2673 B(Jump), U8(-22), //
2674 B(Ldar), R(0), //
2675 B(Star), R(1), //
2676 B(LdaSmi8), U8(1), //
2677 B(Add), R(1), //
2678 B(Star), R(0), //
2679 B(Jump), U8(-34), //
2680 B(LdaUndefined), //
2681 B(Return), //
2682 },
2683 0},
2684 {"for (var x = 0;;) {"
2685 " if (x == 1) break;"
2686 " if (x == 2) continue;"
2687 " x = x + 1;"
2688 "}",
2689 2 * kPointerSize,
2690 1,
2691 41,
2692 {
2693 B(LdaZero), //
2694 B(Star), R(0), //
2695 B(Ldar), R(0), //
2696 B(Star), R(1), //
2697 B(LdaSmi8), U8(1), //
2698 B(TestEqual), R(1), //
2699 B(JumpIfFalse), U8(4), //
2700 B(Jump), U8(26), //
2701 B(Ldar), R(0), //
2702 B(Star), R(1), //
2703 B(LdaSmi8), U8(2), //
2704 B(TestEqual), R(1), //
2705 B(JumpIfFalse), U8(4), //
2706 B(Jump), U8(-22), //
2707 B(Ldar), R(0), //
2708 B(Star), R(1), //
2709 B(LdaSmi8), U8(1), //
2710 B(Add), R(1), //
2711 B(Star), R(0), //
2712 B(Jump), U8(-34), //
2713 B(LdaUndefined), //
2714 B(Return), //
2715 },
2716 0},
2717 {"var x = 0; "
2718 "for (;; x = x + 1) {"
2719 " if (x == 1) break;"
2720 " if (x == 2) continue;"
2721 "}",
2722 2 * kPointerSize,
2723 1,
2724 41,
2725 {
2726 B(LdaZero), //
2727 B(Star), R(0), //
2728 B(Ldar), R(0), //
2729 B(Star), R(1), //
2730 B(LdaSmi8), U8(1), //
2731 B(TestEqual), R(1), //
2732 B(JumpIfFalse), U8(4), //
2733 B(Jump), U8(26), //
2734 B(Ldar), R(0), //
2735 B(Star), R(1), //
2736 B(LdaSmi8), U8(2), //
2737 B(TestEqual), R(1), //
2738 B(JumpIfFalse), U8(4), //
2739 B(Jump), U8(2), //
2740 B(Ldar), R(0), //
2741 B(Star), R(1), //
2742 B(LdaSmi8), U8(1), //
2743 B(Add), R(1), //
2744 B(Star), R(0), //
2745 B(Jump), U8(-34), //
2746 B(LdaUndefined), //
2747 B(Return), //
2748 },
2749 0},
2750 {"for (var x = 0;; x = x + 1) {"
2751 " if (x == 1) break;"
2752 " if (x == 2) continue;"
2753 "}",
2754 2 * kPointerSize,
2755 1,
2756 41,
2757 {
2758 B(LdaZero), //
2759 B(Star), R(0), //
2760 B(Ldar), R(0), //
2761 B(Star), R(1), //
2762 B(LdaSmi8), U8(1), //
2763 B(TestEqual), R(1), //
2764 B(JumpIfFalse), U8(4), //
2765 B(Jump), U8(26), //
2766 B(Ldar), R(0), //
2767 B(Star), R(1), //
2768 B(LdaSmi8), U8(2), //
2769 B(TestEqual), R(1), //
2770 B(JumpIfFalse), U8(4), //
2771 B(Jump), U8(2), //
2772 B(Ldar), R(0), //
2773 B(Star), R(1), //
2774 B(LdaSmi8), U8(1), //
2775 B(Add), R(1), //
2776 B(Star), R(0), //
2777 B(Jump), U8(-34), //
2778 B(LdaUndefined), //
2779 B(Return), //
2780 },
2781 0},
2782 {"var u = 0;"
2783 "for (var i = 0; i < 100; i = i + 1) {"
2784 " u = u + 1;"
2785 " continue;"
2786 "}",
2787 3 * kPointerSize,
2788 1,
2789 42,
2790 {
2791 B(LdaZero), //
2792 B(Star), R(0), //
2793 B(LdaZero), //
2794 B(Star), R(1), //
2795 B(Ldar), R(1), //
2796 B(Star), R(2), //
2797 B(LdaSmi8), U8(100), //
2798 B(TestLessThan), R(2), //
2799 B(JumpIfFalse), U8(26), //
2800 B(Ldar), R(0), //
2801 B(Star), R(2), //
2802 B(LdaSmi8), U8(1), //
2803 B(Add), R(2), //
2804 B(Star), R(0), //
2805 B(Jump), U8(2), //
2806 B(Ldar), R(1), //
2807 B(Star), R(2), //
2808 B(LdaSmi8), U8(1), //
2809 B(Add), R(2), //
2810 B(Star), R(1), //
2811 B(Jump), U8(-32), //
2812 B(LdaUndefined), //
2813 B(Return), //
2814 },
2815 0},
2816 {"var y = 1;"
2817 "for (var x = 10; x; --x) {"
2818 " y = y * 12;"
2819 "}"
2820 "return y;",
2821 3 * kPointerSize,
2822 1,
2823 33,
2824 {
2825 B(LdaSmi8), U8(1), //
2826 B(Star), R(0), //
2827 B(LdaSmi8), U8(10), //
2828 B(Star), R(1), //
2829 B(Ldar), R(1), //
2830 B(JumpIfToBooleanFalse), U8(20), //
2831 B(Ldar), R(0), //
2832 B(Star), R(2), //
2833 B(LdaSmi8), U8(12), //
2834 B(Mul), R(2), //
2835 B(Star), R(0), //
2836 B(Ldar), R(1), //
2837 B(ToNumber), //
2838 B(Dec), //
2839 B(Star), R(1), //
2840 B(Jump), U8(-20), //
2841 B(Ldar), R(0), //
2842 B(Return), //
2843 },
2844 0},
2845 {"var x = 0;"
2846 "for (var i = 0; false; i++) {"
2847 " x = x + 1;"
2848 "};"
2849 "return x;",
2850 2 * kPointerSize,
2851 1,
2852 9,
2853 {
2854 B(LdaZero), //
2855 B(Star), R(0), //
2856 B(LdaZero), //
2857 B(Star), R(1), //
2858 B(Ldar), R(0), //
2859 B(Return), //
2860 },
2861 0},
2862 {"var x = 0;"
2863 "for (var i = 0; true; ++i) {"
2864 " x = x + 1;"
2865 " if (x == 20) break;"
2866 "};"
2867 "return x;",
2868 3 * kPointerSize,
2869 1,
2870 37,
2871 {
2872 B(LdaZero), //
2873 B(Star), R(0), //
2874 B(LdaZero), //
2875 B(Star), R(1), //
2876 B(Ldar), R(0), //
2877 B(Star), R(2), //
2878 B(LdaSmi8), U8(1), //
2879 B(Add), R(2), //
2880 B(Star), R(0), //
2881 B(Star), R(2), //
2882 B(LdaSmi8), U8(20), //
2883 B(TestEqual), R(2), //
2884 B(JumpIfFalse), U8(4), //
2885 B(Jump), U8(10), //
2886 B(Ldar), R(1), //
2887 B(ToNumber), //
2888 B(Inc), //
2889 B(Star), R(1), //
2890 B(Jump), U8(-26), //
2891 B(Ldar), R(0), //
2892 B(Return), //
2893 },
2894 0},
2895 };
2896
2897 for (size_t i = 0; i < arraysize(snippets); i++) {
2898 Handle<BytecodeArray> bytecode_array =
2899 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
2900 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
2901 }
2902}
2903
2904
2905TEST(JumpsRequiringConstantWideOperands) {
2906 InitializedHandleScope handle_scope;
2907 BytecodeGeneratorHelper helper;
2908
2909 int constant_count = 0;
2910 ExpectedSnippet<Handle<Object>, 316> snippets[] = {
2911 {
2912 REPEAT_256(SPACE, "var x = 0.1;")
2913 REPEAT_32(SPACE, "var x = 0.2;")
2914 REPEAT_16(SPACE, "var x = 0.3;")
2915 REPEAT_8(SPACE, "var x = 0.4;")
2916 "for (var i = 0; i < 3; i++) {\n"
2917 " if (i == 1) continue;\n"
2918 " if (i == 2) break;\n"
2919 "}\n"
2920 "return 3;",
2921 kPointerSize * 3,
2922 1,
2923 1359,
2924 {
2925#define L(c) B(LdaConstant), U8(c), B(Star), R(0)
2926 REPEAT_256(COMMA, L(constant_count++)),
2927#undef L
2928#define LW(c) B(LdaConstantWide), U16I(c), B(Star), R(0)
2929 REPEAT_32(COMMA, LW(constant_count)),
2930 REPEAT_16(COMMA, LW(constant_count)),
2931 REPEAT_8(COMMA, LW(constant_count)),
2932#undef LW
2933 B(LdaZero), //
2934 B(Star), R(1), //
2935 B(Ldar), R(1), //
2936 B(Star), R(2), //
2937 B(LdaSmi8), U8(3), //
2938 B(TestLessThan), R(2), //
2939 B(JumpIfFalseConstantWide), U16(313), //
2940 B(Ldar), R(1), //
2941 B(Star), R(2), //
2942 B(LdaSmi8), U8(1), //
2943 B(TestEqual), R(2), //
2944 B(JumpIfFalseConstantWide), U16(312), //
2945 B(JumpConstantWide), U16(315), //
2946 B(Ldar), R(1), //
2947 B(Star), R(2), //
2948 B(LdaSmi8), U8(2), //
2949 B(TestEqual), R(2), //
2950 B(JumpIfFalseConstantWide), U16(312), //
2951 B(JumpConstantWide), U16(314), //
2952 B(Ldar), R(1), //
2953 B(ToNumber), //
2954 B(Star), R(2), //
2955 B(Inc), //
2956 B(Star), R(1), //
2957 B(Jump), U8(-47), //
2958 B(LdaSmi8), U8(3), //
2959 B(Return) //
2960 },
2961 316,
2962 {
2963#define S(x) CcTest::i_isolate()->factory()->NewNumber(x)
2964 REPEAT_256(COMMA, S(0.1)),
2965 REPEAT_32(COMMA, S(0.2)),
2966 REPEAT_16(COMMA, S(0.3)),
2967 REPEAT_8(COMMA, S(0.4)),
2968#undef S
2969#define N(x) CcTest::i_isolate()->factory()->NewNumberFromInt(x)
2970 N(6), N(41), N(13), N(17)
2971#undef N
2972 }}};
2973
2974 for (size_t i = 0; i < arraysize(snippets); i++) {
2975 Handle<BytecodeArray> bytecode_array =
2976 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
2977 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
2978 }
2979}
2980
2981
2982TEST(UnaryOperators) {
2983 InitializedHandleScope handle_scope;
2984 BytecodeGeneratorHelper helper;
2985
2986 ExpectedSnippet<int> snippets[] = {
2987 {"var x = 0;"
2988 "while (x != 10) {"
2989 " x = x + 10;"
2990 "}"
2991 "return x;",
2992 2 * kPointerSize,
2993 1,
2994 29,
2995 {
2996 B(LdaZero), //
2997 B(Star), R(0), //
2998 B(Ldar), R(0), //
2999 B(Star), R(1), //
3000 B(LdaSmi8), U8(10), //
3001 B(TestEqual), R(1), //
3002 B(LogicalNot), //
3003 B(JumpIfFalse), U8(14), //
3004 B(Ldar), R(0), //
3005 B(Star), R(1), //
3006 B(LdaSmi8), U8(10), //
3007 B(Add), R(1), //
3008 B(Star), R(0), //
3009 B(Jump), U8(-21), //
3010 B(Ldar), R(0), //
3011 B(Return), //
3012 },
3013 0},
3014 {"var x = false;"
3015 "do {"
3016 " x = !x;"
3017 "} while(x == false);"
3018 "return x;",
3019 2 * kPointerSize,
3020 1,
3021 20,
3022 {
3023 B(LdaFalse), //
3024 B(Star), R(0), //
3025 B(Ldar), R(0), //
3026 B(LogicalNot), //
3027 B(Star), R(0), //
3028 B(Ldar), R(0), //
3029 B(Star), R(1), //
3030 B(LdaFalse), //
3031 B(TestEqual), R(1), //
3032 B(JumpIfTrue), U8(-12), //
3033 B(Ldar), R(0), //
3034 B(Return), //
3035 },
3036 0},
3037 {"var x = 101;"
3038 "return void(x * 3);",
3039 2 * kPointerSize,
3040 1,
3041 12,
3042 {
3043 B(LdaSmi8), U8(101), //
3044 B(Star), R(0), //
3045 B(Star), R(1), //
3046 B(LdaSmi8), U8(3), //
3047 B(Mul), R(1), //
3048 B(LdaUndefined), //
3049 B(Return), //
3050 },
3051 0},
3052 {"var x = 1234;"
3053 "var y = void (x * x - 1);"
3054 "return y;",
3055 4 * kPointerSize,
3056 1,
3057 20,
3058 {
3059 B(LdaConstant), U8(0), //
3060 B(Star), R(0), //
3061 B(Star), R(2), //
3062 B(Ldar), R(0), //
3063 B(Mul), R(2), //
3064 B(Star), R(3), //
3065 B(LdaSmi8), U8(1), //
3066 B(Sub), R(3), //
3067 B(LdaUndefined), //
3068 B(Star), R(1), //
3069 B(Return), //
3070 },
3071 1,
3072 {1234}},
3073 {"var x = 13;"
3074 "return ~x;",
3075 2 * kPointerSize,
3076 1,
3077 11,
3078 {
3079 B(LdaSmi8), U8(13), //
3080 B(Star), R(0), //
3081 B(Star), R(1), //
3082 B(LdaSmi8), U8(-1), //
3083 B(BitwiseXor), R(1), //
3084 B(Return), //
3085 },
3086 0},
3087 {"var x = 13;"
3088 "return +x;",
3089 2 * kPointerSize,
3090 1,
3091 11,
3092 {
3093 B(LdaSmi8), U8(13), //
3094 B(Star), R(0), //
3095 B(Star), R(1), //
3096 B(LdaSmi8), U8(1), //
3097 B(Mul), R(1), //
3098 B(Return), //
3099 },
3100 0},
3101 {"var x = 13;"
3102 "return -x;",
3103 2 * kPointerSize,
3104 1,
3105 11,
3106 {
3107 B(LdaSmi8), U8(13), //
3108 B(Star), R(0), //
3109 B(Star), R(1), //
3110 B(LdaSmi8), U8(-1), //
3111 B(Mul), R(1), //
3112 B(Return), //
3113 },
3114 0}};
3115
3116 for (size_t i = 0; i < arraysize(snippets); i++) {
3117 Handle<BytecodeArray> bytecode_array =
3118 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
3119 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
3120 }
3121}
3122
3123
3124TEST(Typeof) {
3125 InitializedHandleScope handle_scope;
3126 BytecodeGeneratorHelper helper;
3127 Zone zone;
3128
3129 FeedbackVectorSpec feedback_spec(&zone);
3130 FeedbackVectorSlot slot = feedback_spec.AddLoadICSlot();
3131
3132 Handle<i::TypeFeedbackVector> vector =
3133 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
3134
3135 ExpectedSnippet<const char*> snippets[] = {
3136 {"function f() {\n"
3137 " var x = 13;\n"
3138 " return typeof(x);\n"
3139 "}; f();",
3140 kPointerSize,
3141 1,
3142 6,
3143 {
3144 B(LdaSmi8), U8(13), //
3145 B(Star), R(0), //
3146 B(TypeOf), //
3147 B(Return), //
3148 }},
3149 {"var x = 13;\n"
3150 "function f() {\n"
3151 " return typeof(x);\n"
3152 "}; f();",
3153 0,
3154 1,
3155 5,
3156 {
3157 B(LdaGlobalInsideTypeofSloppy), U8(0), //
3158 U8(vector->GetIndex(slot)), //
3159 B(TypeOf), //
3160 B(Return), //
3161 },
3162 1,
3163 {"x"}},
3164 {"var x = 13;\n"
3165 "function f() {\n"
3166 " 'use strict';\n"
3167 " return typeof(x);\n"
3168 "}; f();",
3169 0,
3170 1,
3171 5,
3172 {
3173 B(LdaGlobalInsideTypeofStrict), U8(0), //
3174 U8(vector->GetIndex(slot)), //
3175 B(TypeOf), //
3176 B(Return), //
3177 },
3178 1,
3179 {"x"}},
3180 };
3181
3182 for (size_t i = 0; i < arraysize(snippets); i++) {
3183 Handle<BytecodeArray> bytecode_array =
3184 helper.MakeBytecodeForFunction(snippets[i].code_snippet);
3185 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
3186 }
3187}
3188
3189
3190TEST(Delete) {
3191 InitializedHandleScope handle_scope;
3192 BytecodeGeneratorHelper helper;
3193
3194 int deep_elements_flags =
3195 ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos;
3196 int closure = Register::function_closure().index();
3197 int first_context_slot = Context::MIN_CONTEXT_SLOTS;
3198
3199 ExpectedSnippet<InstanceType> snippets[] = {
3200 {"var a = {x:13, y:14}; return delete a.x;",
3201 2 * kPointerSize,
3202 1,
3203 13,
3204 {
3205 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
3206 B(Star), R(0), //
3207 B(Star), R(1), //
3208 B(LdaConstant), U8(1), //
3209 B(DeletePropertySloppy), R(1), //
3210 B(Return)
3211 },
3212 2,
3213 {InstanceType::FIXED_ARRAY_TYPE,
3214 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
3215 {"'use strict'; var a = {x:13, y:14}; return delete a.x;",
3216 2 * kPointerSize,
3217 1,
3218 13,
3219 {
3220 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
3221 B(Star), R(0), //
3222 B(Star), R(1), //
3223 B(LdaConstant), U8(1), //
3224 B(DeletePropertyStrict), R(1), //
3225 B(Return)
3226 },
3227 2,
3228 {InstanceType::FIXED_ARRAY_TYPE,
3229 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
3230 {"var a = {1:13, 2:14}; return delete a[2];",
3231 2 * kPointerSize,
3232 1,
3233 13,
3234 {
3235 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
3236 B(Star), R(0), //
3237 B(Star), R(1), //
3238 B(LdaSmi8), U8(2), //
3239 B(DeletePropertySloppy), R(1), //
3240 B(Return)
3241 },
3242 1,
3243 {InstanceType::FIXED_ARRAY_TYPE}},
3244 {"var a = 10; return delete a;",
3245 1 * kPointerSize,
3246 1,
3247 6,
3248 {
3249 B(LdaSmi8), U8(10), //
3250 B(Star), R(0), //
3251 B(LdaFalse), //
3252 B(Return)
3253 },
3254 0},
3255 {"'use strict';"
3256 "var a = {1:10};"
3257 "(function f1() {return a;});"
3258 "return delete a[1];",
3259 2 * kPointerSize,
3260 1,
3261 27,
3262 {
3263 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
3264 R(closure), U8(1), //
3265 B(PushContext), R(0), //
3266 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
3267 B(StaContextSlot), R(0), U8(first_context_slot), //
3268 B(CreateClosure), U8(1), U8(0), //
3269 B(LdaContextSlot), R(0), U8(first_context_slot), //
3270 B(Star), R(1), //
3271 B(LdaSmi8), U8(1), //
3272 B(DeletePropertyStrict), R(1), //
3273 B(Return)
3274 },
3275 2,
3276 {InstanceType::FIXED_ARRAY_TYPE,
3277 InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3278 {"return delete 'test';",
3279 0 * kPointerSize,
3280 1,
3281 2,
3282 {
3283 B(LdaTrue), //
3284 B(Return)
3285 },
3286 0},
3287 };
3288
3289 for (size_t i = 0; i < arraysize(snippets); i++) {
3290 Handle<BytecodeArray> bytecode_array =
3291 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
3292 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
3293 }
3294}
3295
3296
3297TEST(GlobalDelete) {
3298 InitializedHandleScope handle_scope;
3299 BytecodeGeneratorHelper helper;
3300 Zone zone;
3301
3302 int context = Register::function_context().index();
3303 int native_context_index = Context::NATIVE_CONTEXT_INDEX;
3304 int global_context_index = Context::EXTENSION_INDEX;
3305 FeedbackVectorSpec feedback_spec(&zone);
3306 FeedbackVectorSlot slot = feedback_spec.AddLoadICSlot();
3307
3308 Handle<i::TypeFeedbackVector> vector =
3309 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
3310
3311 ExpectedSnippet<InstanceType> snippets[] = {
3312 {"var a = {x:13, y:14};\n function f() { return delete a.x; };\n f();",
3313 1 * kPointerSize,
3314 1,
3315 10,
3316 {B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
3317 B(Star), R(0), //
3318 B(LdaConstant), U8(1), //
3319 B(DeletePropertySloppy), R(0), //
3320 B(Return)},
3321 2,
3322 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
3323 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
3324 {"a = {1:13, 2:14};\n"
3325 "function f() {'use strict'; return delete a[1];};\n f();",
3326 1 * kPointerSize,
3327 1,
3328 10,
3329 {B(LdaGlobalStrict), U8(0), U8(vector->GetIndex(slot)), //
3330 B(Star), R(0), //
3331 B(LdaSmi8), U8(1), //
3332 B(DeletePropertyStrict), R(0), //
3333 B(Return)},
3334 1,
3335 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
3336 {"var a = {x:13, y:14};\n function f() { return delete a; };\n f();",
3337 2 * kPointerSize,
3338 1,
3339 15,
3340 {B(LdaContextSlot), R(context), U8(native_context_index), //
3341 B(Star), R(0), //
3342 B(LdaContextSlot), R(0), U8(global_context_index), //
3343 B(Star), R(1), //
3344 B(LdaConstant), U8(0), //
3345 B(DeletePropertySloppy), R(1), //
3346 B(Return)},
3347 1,
3348 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
3349 {"b = 30;\n function f() { return delete b; };\n f();",
3350 2 * kPointerSize,
3351 1,
3352 15,
3353 {B(LdaContextSlot), R(context), U8(native_context_index), //
3354 B(Star), R(0), //
3355 B(LdaContextSlot), R(0), U8(global_context_index), //
3356 B(Star), R(1), //
3357 B(LdaConstant), U8(0), //
3358 B(DeletePropertySloppy), R(1), //
3359 B(Return)},
3360 1,
3361 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}};
3362
3363 for (size_t i = 0; i < arraysize(snippets); i++) {
3364 Handle<BytecodeArray> bytecode_array =
3365 helper.MakeBytecode(snippets[i].code_snippet, "f");
3366 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
3367 }
3368}
3369
3370
3371TEST(FunctionLiterals) {
3372 InitializedHandleScope handle_scope;
3373 BytecodeGeneratorHelper helper;
3374 Zone zone;
3375
3376 FeedbackVectorSpec feedback_spec(&zone);
3377 FeedbackVectorSlot slot = feedback_spec.AddCallICSlot();
3378
3379 Handle<i::TypeFeedbackVector> vector =
3380 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
3381
3382 ExpectedSnippet<InstanceType> snippets[] = {
3383 {"return function(){ }",
3384 0,
3385 1,
3386 4,
3387 {
3388 B(CreateClosure), U8(0), U8(0), //
3389 B(Return) //
3390 },
3391 1,
3392 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3393 {"return (function(){ })()",
3394 2 * kPointerSize,
3395 1,
3396 14,
3397 {
3398 B(LdaUndefined), //
3399 B(Star), R(1), //
3400 B(CreateClosure), U8(0), U8(0), //
3401 B(Star), R(0), //
3402 B(Call), R(0), R(1), U8(0), U8(vector->GetIndex(slot)), //
3403 B(Return) //
3404 },
3405 1,
3406 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3407 {"return (function(x){ return x; })(1)",
3408 3 * kPointerSize,
3409 1,
3410 18,
3411 {
3412 B(LdaUndefined), //
3413 B(Star), R(1), //
3414 B(CreateClosure), U8(0), U8(0), //
3415 B(Star), R(0), //
3416 B(LdaSmi8), U8(1), //
3417 B(Star), R(2), //
3418 B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot)), //
3419 B(Return) //
3420 },
3421 1,
3422 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3423 };
3424
3425 for (size_t i = 0; i < arraysize(snippets); i++) {
3426 Handle<BytecodeArray> bytecode_array =
3427 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
3428 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
3429 }
3430}
3431
3432
3433TEST(RegExpLiterals) {
3434 InitializedHandleScope handle_scope;
3435 BytecodeGeneratorHelper helper;
3436 Zone zone;
3437
3438 FeedbackVectorSpec feedback_spec(&zone);
3439 FeedbackVectorSlot slot1 = feedback_spec.AddCallICSlot();
3440 FeedbackVectorSlot slot2 = feedback_spec.AddLoadICSlot();
3441 uint8_t i_flags = JSRegExp::kIgnoreCase;
3442
3443 Handle<i::TypeFeedbackVector> vector =
3444 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
3445
3446 ExpectedSnippet<const char*> snippets[] = {
3447 {"return /ab+d/;",
3448 0 * kPointerSize,
3449 1,
3450 5,
3451 {
3452 B(CreateRegExpLiteral), U8(0), U8(0), U8(0), //
3453 B(Return), //
3454 },
3455 1,
3456 {"ab+d"}},
3457 {"return /(\\w+)\\s(\\w+)/i;",
3458 0 * kPointerSize,
3459 1,
3460 5,
3461 {
3462 B(CreateRegExpLiteral), U8(0), U8(0), U8(i_flags), //
3463 B(Return), //
3464 },
3465 1,
3466 {"(\\w+)\\s(\\w+)"}},
3467 {"return /ab+d/.exec('abdd');",
3468 3 * kPointerSize,
3469 1,
3470 22,
3471 {
3472 B(CreateRegExpLiteral), U8(0), U8(0), U8(0), //
3473 B(Star), R(1), //
3474 B(LoadICSloppy), R(1), U8(1), U8(vector->GetIndex(slot2)), //
3475 B(Star), R(0), //
3476 B(LdaConstant), U8(2), //
3477 B(Star), R(2), //
3478 B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot1)), //
3479 B(Return), //
3480 },
3481 3,
3482 {"ab+d", "exec", "abdd"}},
3483 };
3484
3485 for (size_t i = 0; i < arraysize(snippets); i++) {
3486 Handle<BytecodeArray> bytecode_array =
3487 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
3488 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
3489 }
3490}
3491
3492
3493TEST(RegExpLiteralsWide) {
3494 InitializedHandleScope handle_scope;
3495 BytecodeGeneratorHelper helper;
3496 Zone zone;
3497
3498 int wide_idx = 0;
3499
3500 ExpectedSnippet<InstanceType, 257> snippets[] = {
3501 {"var a;" REPEAT_256(SPACE, "a = 1.23;") "return /ab+d/;",
3502 1 * kPointerSize,
3503 1,
3504 1031,
3505 {
3506 REPEAT_256(COMMA, //
3507 B(LdaConstant), U8(wide_idx++), //
3508 B(Star), R(0)), //
3509 B(CreateRegExpLiteralWide), U16(256), U16(0), U8(0), //
3510 B(Return) //
3511 },
3512 257,
3513 {REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE),
3514 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
3515 };
3516
3517 for (size_t i = 0; i < arraysize(snippets); i++) {
3518 Handle<BytecodeArray> bytecode_array =
3519 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
3520 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
3521 }
3522}
3523
3524
3525TEST(ArrayLiterals) {
3526 InitializedHandleScope handle_scope;
3527 BytecodeGeneratorHelper helper;
3528 Zone zone;
3529
3530 FeedbackVectorSpec feedback_spec(&zone);
3531 FeedbackVectorSlot slot1 = feedback_spec.AddKeyedStoreICSlot();
3532 FeedbackVectorSlot slot2 = feedback_spec.AddKeyedStoreICSlot();
3533 FeedbackVectorSlot slot3 = feedback_spec.AddKeyedStoreICSlot();
3534
3535 Handle<i::TypeFeedbackVector> vector =
3536 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
3537
3538 int simple_flags =
3539 ArrayLiteral::kDisableMementos | ArrayLiteral::kShallowElements;
3540 int deep_elements_flags = ArrayLiteral::kDisableMementos;
3541 ExpectedSnippet<InstanceType> snippets[] = {
3542 {"return [ 1, 2 ];",
3543 0,
3544 1,
3545 5,
3546 {
3547 B(CreateArrayLiteral), U8(0), U8(0), U8(simple_flags), //
3548 B(Return) //
3549 },
3550 1,
3551 {InstanceType::FIXED_ARRAY_TYPE}},
3552 {"var a = 1; return [ a, a + 1 ];",
3553 4 * kPointerSize,
3554 1,
3555 38,
3556 {
3557 B(LdaSmi8), U8(1), //
3558 B(Star), R(0), //
3559 B(CreateArrayLiteral), U8(0), U8(0), U8(3), //
3560 B(Star), R(2), //
3561 B(LdaZero), //
3562 B(Star), R(1), //
3563 B(Ldar), R(0), //
3564 B(KeyedStoreICSloppy), R(2), R(1), U8(vector->GetIndex(slot1)), //
3565 B(LdaSmi8), U8(1), //
3566 B(Star), R(1), //
3567 B(Ldar), R(0), //
3568 B(Star), R(3), //
3569 B(LdaSmi8), U8(1), //
3570 B(Add), R(3), //
3571 B(KeyedStoreICSloppy), R(2), R(1), U8(vector->GetIndex(slot1)), //
3572 B(Ldar), R(2), //
3573 B(Return), //
3574 },
3575 1,
3576 {InstanceType::FIXED_ARRAY_TYPE}},
3577 {"return [ [ 1, 2 ], [ 3 ] ];",
3578 0,
3579 1,
3580 5,
3581 {
3582 B(CreateArrayLiteral), U8(0), U8(2), U8(deep_elements_flags), //
3583 B(Return) //
3584 },
3585 1,
3586 {InstanceType::FIXED_ARRAY_TYPE}},
3587 {"var a = 1; return [ [ a, 2 ], [ a + 2 ] ];",
3588 6 * kPointerSize,
3589 1,
3590 68,
3591 {
3592 B(LdaSmi8), U8(1), //
3593 B(Star), R(0), //
3594 B(CreateArrayLiteral), U8(0), U8(2), U8(deep_elements_flags), //
3595 B(Star), R(2), //
3596 B(LdaZero), //
3597 B(Star), R(1), //
3598 B(CreateArrayLiteral), U8(1), U8(0), U8(simple_flags), //
3599 B(Star), R(4), //
3600 B(LdaZero), //
3601 B(Star), R(3), //
3602 B(Ldar), R(0), //
3603 B(KeyedStoreICSloppy), R(4), R(3), U8(vector->GetIndex(slot1)), //
3604 B(Ldar), R(4), //
3605 B(KeyedStoreICSloppy), R(2), R(1), U8(vector->GetIndex(slot3)), //
3606 B(LdaSmi8), U8(1), //
3607 B(Star), R(1), //
3608 B(CreateArrayLiteral), U8(2), U8(1), U8(simple_flags), //
3609 B(Star), R(4), //
3610 B(LdaZero), //
3611 B(Star), R(3), //
3612 B(Ldar), R(0), //
3613 B(Star), R(5), //
3614 B(LdaSmi8), U8(2), //
3615 B(Add), R(5), //
3616 B(KeyedStoreICSloppy), R(4), R(3), U8(vector->GetIndex(slot2)), //
3617 B(Ldar), R(4), //
3618 B(KeyedStoreICSloppy), R(2), R(1), U8(vector->GetIndex(slot3)), //
3619 B(Ldar), R(2), //
3620 B(Return), //
3621 },
3622 3,
3623 {InstanceType::FIXED_ARRAY_TYPE, InstanceType::FIXED_ARRAY_TYPE,
3624 InstanceType::FIXED_ARRAY_TYPE}},
3625 };
3626
3627 for (size_t i = 0; i < arraysize(snippets); i++) {
3628 Handle<BytecodeArray> bytecode_array =
3629 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
3630 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
3631 }
3632}
3633
3634
3635TEST(ArrayLiteralsWide) {
3636 InitializedHandleScope handle_scope;
3637 BytecodeGeneratorHelper helper;
3638 Zone zone;
3639
3640 int wide_idx = 0;
3641 int simple_flags =
3642 ArrayLiteral::kDisableMementos | ArrayLiteral::kShallowElements;
3643
3644 ExpectedSnippet<InstanceType, 257> snippets[] = {
3645 {"var a;" REPEAT_256(SPACE, "a = 1.23;") "return [ 1 , 2 ];",
3646 1 * kPointerSize,
3647 1,
3648 1031,
3649 {
3650 REPEAT_256(COMMA, //
3651 B(LdaConstant), U8(wide_idx++), //
3652 B(Star), R(0)), //
3653 B(CreateArrayLiteralWide), U16(256), U16(0), U8(simple_flags), //
3654 B(Return) //
3655 },
3656 257,
3657 {REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE),
3658 InstanceType::FIXED_ARRAY_TYPE}},
3659 };
3660
3661 for (size_t i = 0; i < arraysize(snippets); i++) {
3662 Handle<BytecodeArray> bytecode_array =
3663 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
3664 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
3665 }
3666}
3667
3668
3669TEST(ObjectLiterals) {
3670 InitializedHandleScope handle_scope;
3671 BytecodeGeneratorHelper helper;
3672 Zone zone;
3673
3674 FeedbackVectorSpec feedback_spec(&zone);
3675 FeedbackVectorSlot slot1 = feedback_spec.AddStoreICSlot();
3676
3677 Handle<i::TypeFeedbackVector> vector =
3678 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
3679
3680 int simple_flags = ObjectLiteral::kFastElements |
3681 ObjectLiteral::kShallowProperties |
3682 ObjectLiteral::kDisableMementos;
3683 int deep_elements_flags =
3684 ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos;
3685 ExpectedSnippet<InstanceType> snippets[] = {
3686 {"return { };",
3687 0,
3688 1,
3689 5,
3690 {
3691 B(CreateObjectLiteral), U8(0), U8(0), U8(simple_flags), //
3692 B(Return) //
3693 },
3694 1,
3695 {InstanceType::FIXED_ARRAY_TYPE}},
3696 {"return { name: 'string', val: 9.2 };",
3697 0,
3698 1,
3699 5,
3700 {
3701 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
3702 B(Return) //
3703 },
3704 1,
3705 {InstanceType::FIXED_ARRAY_TYPE}},
3706 {"var a = 1; return { name: 'string', val: a };",
3707 2 * kPointerSize,
3708 1,
3709 19,
3710 {
3711 B(LdaSmi8), U8(1), //
3712 B(Star), R(0), //
3713 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
3714 B(Star), R(1), //
3715 B(Ldar), R(0), //
3716 B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), //
3717 B(Ldar), R(1), //
3718 B(Return), //
3719 },
3720 2,
3721 {InstanceType::FIXED_ARRAY_TYPE,
3722 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
3723 {"var a = 1; return { val: a, val: a + 1 };",
3724 3 * kPointerSize,
3725 1,
3726 25,
3727 {
3728 B(LdaSmi8), U8(1), //
3729 B(Star), R(0), //
3730 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
3731 B(Star), R(1), //
3732 B(Ldar), R(0), //
3733 B(Star), R(2), //
3734 B(LdaSmi8), U8(1), //
3735 B(Add), R(2), //
3736 B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), //
3737 B(Ldar), R(1), //
3738 B(Return), //
3739 },
3740 2,
3741 {InstanceType::FIXED_ARRAY_TYPE,
3742 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
3743 {"return { func: function() { } };",
3744 1 * kPointerSize,
3745 1,
3746 16,
3747 {
3748 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
3749 B(Star), R(0), //
3750 B(CreateClosure), U8(1), U8(0), //
3751 B(StoreICSloppy), R(0), U8(2), U8(vector->GetIndex(slot1)), //
3752 B(Ldar), R(0), //
3753 B(Return), //
3754 },
3755 3,
3756 {InstanceType::FIXED_ARRAY_TYPE,
3757 InstanceType::SHARED_FUNCTION_INFO_TYPE,
3758 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
3759 {"return { func(a) { return a; } };",
3760 1 * kPointerSize,
3761 1,
3762 16,
3763 {
3764 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
3765 B(Star), R(0), //
3766 B(CreateClosure), U8(1), U8(0), //
3767 B(StoreICSloppy), R(0), U8(2), U8(vector->GetIndex(slot1)), //
3768 B(Ldar), R(0), //
3769 B(Return), //
3770 },
3771 3,
3772 {InstanceType::FIXED_ARRAY_TYPE,
3773 InstanceType::SHARED_FUNCTION_INFO_TYPE,
3774 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
3775 {"return { get a() { return 2; } };",
3776 5 * kPointerSize,
3777 1,
3778 29,
3779 {
3780 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
3781 B(Star), R(0), //
3782 B(LdaConstant), U8(1), //
3783 B(Star), R(1), //
3784 B(CreateClosure), U8(2), U8(0), //
3785 B(Star), R(2), //
3786 B(LdaNull), //
3787 B(Star), R(3), //
3788 B(LdaZero), //
3789 B(Star), R(4), //
3790 B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), //
3791 R(0), U8(5), //
3792 B(Ldar), R(0), //
3793 B(Return), //
3794 },
3795 3,
3796 {InstanceType::FIXED_ARRAY_TYPE,
3797 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
3798 InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3799 {"return { get a() { return this.x; }, set a(val) { this.x = val } };",
3800 5 * kPointerSize,
3801 1,
3802 31,
3803 {
3804 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
3805 B(Star), R(0), //
3806 B(LdaConstant), U8(1), //
3807 B(Star), R(1), //
3808 B(CreateClosure), U8(2), U8(0), //
3809 B(Star), R(2), //
3810 B(CreateClosure), U8(3), U8(0), //
3811 B(Star), R(3), //
3812 B(LdaZero), //
3813 B(Star), R(4), //
3814 B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), //
3815 R(0), U8(5), //
3816 B(Ldar), R(0), //
3817 B(Return), //
3818 },
3819 4,
3820 {InstanceType::FIXED_ARRAY_TYPE,
3821 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
3822 InstanceType::SHARED_FUNCTION_INFO_TYPE,
3823 InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3824 {"return { set b(val) { this.y = val } };",
3825 5 * kPointerSize,
3826 1,
3827 29,
3828 {
3829 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
3830 B(Star), R(0), //
3831 B(LdaConstant), U8(1), //
3832 B(Star), R(1), //
3833 B(LdaNull), //
3834 B(Star), R(2), //
3835 B(CreateClosure), U8(2), U8(0), //
3836 B(Star), R(3), //
3837 B(LdaZero), //
3838 B(Star), R(4), //
3839 B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), //
3840 R(0), U8(5), //
3841 B(Ldar), R(0), //
3842 B(Return), //
3843 },
3844 3,
3845 {InstanceType::FIXED_ARRAY_TYPE,
3846 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
3847 InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3848 {"var a = 1; return { 1: a };",
3849 5 * kPointerSize,
3850 1,
3851 29,
3852 {
3853 B(LdaSmi8), U8(1), //
3854 B(Star), R(0), //
3855 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
3856 B(Star), R(1), //
3857 B(LdaSmi8), U8(1), //
3858 B(Star), R(2), //
3859 B(Ldar), R(0), //
3860 B(Star), R(3), //
3861 B(LdaZero), //
3862 B(Star), R(4), //
3863 B(CallRuntime), U16(Runtime::kSetProperty), R(1), U8(4), //
3864 B(Ldar), R(1), //
3865 B(Return), //
3866 },
3867 1,
3868 {InstanceType::FIXED_ARRAY_TYPE}},
3869 {"return { __proto__: null }",
3870 2 * kPointerSize,
3871 1,
3872 17,
3873 {
3874 B(CreateObjectLiteral), U8(0), U8(0), U8(simple_flags), //
3875 B(Star), R(0), //
3876 B(LdaNull), B(Star), R(1), //
3877 B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(0), U8(2), //
3878 B(Ldar), R(0), //
3879 B(Return), //
3880 },
3881 1,
3882 {InstanceType::FIXED_ARRAY_TYPE}},
3883 {"var a = 'test'; return { [a]: 1 }",
3884 5 * kPointerSize,
3885 1,
3886 30,
3887 {
3888 B(LdaConstant), U8(0), //
3889 B(Star), R(0), //
3890 B(CreateObjectLiteral), U8(1), U8(0), U8(simple_flags), //
3891 B(Star), R(1), //
3892 B(Ldar), R(0), //
3893 B(ToName), //
3894 B(Star), R(2), //
3895 B(LdaSmi8), U8(1), //
3896 B(Star), R(3), //
3897 B(LdaZero), //
3898 B(Star), R(4), //
3899 B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1), //
3900 U8(4), //
3901 B(Ldar), R(1), //
3902 B(Return), //
3903 },
3904 2,
3905 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
3906 InstanceType::FIXED_ARRAY_TYPE}},
3907 {"var a = 'test'; return { val: a, [a]: 1 }",
3908 5 * kPointerSize,
3909 1,
3910 36,
3911 {
3912 B(LdaConstant), U8(0), //
3913 B(Star), R(0), //
3914 B(CreateObjectLiteral), U8(1), U8(0), U8(deep_elements_flags), //
3915 B(Star), R(1), //
3916 B(Ldar), R(0), //
3917 B(StoreICSloppy), R(1), U8(2), U8(vector->GetIndex(slot1)), //
3918 B(Ldar), R(0), //
3919 B(ToName), //
3920 B(Star), R(2), //
3921 B(LdaSmi8), U8(1), //
3922 B(Star), R(3), //
3923 B(LdaZero), //
3924 B(Star), R(4), //
3925 B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1), //
3926 U8(4), //
3927 B(Ldar), R(1), //
3928 B(Return), //
3929 },
3930 3,
3931 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
3932 InstanceType::FIXED_ARRAY_TYPE,
3933 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
3934 {"var a = 'test'; return { [a]: 1, __proto__: {} }",
3935 5 * kPointerSize,
3936 1,
3937 41,
3938 {
3939 B(LdaConstant), U8(0), //
3940 B(Star), R(0), //
3941 B(CreateObjectLiteral), U8(1), U8(1), U8(simple_flags), //
3942 B(Star), R(1), //
3943 B(Ldar), R(0), //
3944 B(ToName), //
3945 B(Star), R(2), //
3946 B(LdaSmi8), U8(1), //
3947 B(Star), R(3), //
3948 B(LdaZero), //
3949 B(Star), R(4), //
3950 B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1), //
3951 U8(4), //
3952 B(CreateObjectLiteral), U8(1), U8(0), U8(13), //
3953 B(Star), R(2), //
3954 B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(1), U8(2), //
3955 B(Ldar), R(1), //
3956 B(Return), //
3957 },
3958 2,
3959 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
3960 InstanceType::FIXED_ARRAY_TYPE}},
3961 {"var n = 'name'; return { [n]: 'val', get a() { }, set a(b) {} };",
3962 5 * kPointerSize,
3963 1,
3964 64,
3965 {
3966 B(LdaConstant), U8(0), //
3967 B(Star), R(0), //
3968 B(CreateObjectLiteral), U8(1), U8(0), U8(simple_flags), //
3969 B(Star), R(1), //
3970 B(Ldar), R(0), //
3971 B(ToName), //
3972 B(Star), R(2), //
3973 B(LdaConstant), U8(2), //
3974 B(Star), R(3), //
3975 B(LdaZero), //
3976 B(Star), R(4), //
3977 B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1), //
3978 U8(4), //
3979 B(LdaConstant), U8(3), //
3980 B(Star), R(2), //
3981 B(CreateClosure), U8(4), U8(0), //
3982 B(Star), R(3), //
3983 B(LdaZero), //
3984 B(Star), R(4), //
3985 B(CallRuntime), U16(Runtime::kDefineGetterPropertyUnchecked), //
3986 R(1), U8(4), //
3987 B(LdaConstant), U8(3), //
3988 B(Star), R(2), //
3989 B(CreateClosure), U8(5), U8(0), //
3990 B(Star), R(3), //
3991 B(LdaZero), //
3992 B(Star), R(4), //
3993 B(CallRuntime), U16(Runtime::kDefineSetterPropertyUnchecked), //
3994 R(1), U8(4), //
3995 B(Ldar), R(1), //
3996 B(Return), //
3997 },
3998 6,
3999 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
4000 InstanceType::FIXED_ARRAY_TYPE,
4001 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
4002 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
4003 InstanceType::SHARED_FUNCTION_INFO_TYPE,
4004 InstanceType::SHARED_FUNCTION_INFO_TYPE}},
4005 };
4006
4007 for (size_t i = 0; i < arraysize(snippets); i++) {
4008 Handle<BytecodeArray> bytecode_array =
4009 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
4010 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
4011 }
4012}
4013
4014
4015TEST(ObjectLiteralsWide) {
4016 InitializedHandleScope handle_scope;
4017 BytecodeGeneratorHelper helper;
4018 Zone zone;
4019
4020 int deep_elements_flags =
4021 ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos;
4022 int wide_idx = 0;
4023
4024 ExpectedSnippet<InstanceType, 257> snippets[] = {
4025 {"var a;" REPEAT_256(SPACE,
4026 "a = 1.23;") "return { name: 'string', val: 9.2 };",
4027 1 * kPointerSize,
4028 1,
4029 1031,
4030 {
4031 REPEAT_256(COMMA, //
4032 B(LdaConstant), U8(wide_idx++), //
4033 B(Star), R(0)), //
4034 B(CreateObjectLiteralWide), U16(256), U16(0), //
4035 U8(deep_elements_flags), //
4036 B(Return) //
4037 },
4038 257,
4039 {REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE),
4040 InstanceType::FIXED_ARRAY_TYPE}},
4041 };
4042
4043 for (size_t i = 0; i < arraysize(snippets); i++) {
4044 Handle<BytecodeArray> bytecode_array =
4045 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
4046 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
4047 }
4048}
4049
4050
4051TEST(TopLevelObjectLiterals) {
4052 InitializedHandleScope handle_scope;
4053 BytecodeGeneratorHelper helper;
4054
4055 int has_function_flags = ObjectLiteral::kFastElements |
4056 ObjectLiteral::kHasFunction |
4057 ObjectLiteral::kDisableMementos;
4058 ExpectedSnippet<InstanceType> snippets[] = {
4059 {"var a = { func: function() { } };",
4060 5 * kPointerSize,
4061 1,
4062 48,
4063 {
4064 B(LdaConstant), U8(0), //
4065 B(Star), R(1), //
4066 B(LdaZero), //
4067 B(Star), R(2), //
4068 B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2), //
4069 B(LdaConstant), U8(1), //
4070 B(Star), R(1), //
4071 B(LdaZero), //
4072 B(Star), R(2), //
4073 B(CreateObjectLiteral), U8(2), U8(0), U8(has_function_flags), //
4074 B(Star), R(4), //
4075 B(CreateClosure), U8(3), U8(1), //
4076 B(StoreICSloppy), R(4), U8(4), U8(3), //
4077 B(CallRuntime), U16(Runtime::kToFastProperties), R(4), U8(1), //
4078 B(Ldar), R(4), //
4079 B(Star), R(3), //
4080 B(CallRuntime), U16(Runtime::kInitializeVarGlobal), R(1), U8(3), //
4081 B(LdaUndefined), //
4082 B(Return), //
4083 },
4084 5,
4085 {InstanceType::FIXED_ARRAY_TYPE,
4086 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
4087 InstanceType::FIXED_ARRAY_TYPE,
4088 InstanceType::SHARED_FUNCTION_INFO_TYPE,
4089 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
4090 };
4091
4092 for (size_t i = 0; i < arraysize(snippets); i++) {
4093 Handle<BytecodeArray> bytecode_array =
4094 helper.MakeTopLevelBytecode(snippets[i].code_snippet);
4095 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
4096 }
4097}
4098
4099
4100TEST(TryCatch) {
4101 InitializedHandleScope handle_scope;
4102 BytecodeGeneratorHelper helper;
4103
4104 // TODO(rmcilroy): modify tests when we have real try catch support.
4105 ExpectedSnippet<int> snippets[] = {
4106 {"try { return 1; } catch(e) { return 2; }",
4107 kPointerSize,
4108 1,
4109 3,
4110 {
4111 B(LdaSmi8), U8(1), //
4112 B(Return), //
4113 },
4114 0},
4115 };
4116
4117 for (size_t i = 0; i < arraysize(snippets); i++) {
4118 Handle<BytecodeArray> bytecode_array =
4119 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
4120 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
4121 }
4122}
4123
4124
4125TEST(TryFinally) {
4126 InitializedHandleScope handle_scope;
4127 BytecodeGeneratorHelper helper;
4128
4129 // TODO(rmcilroy): modify tests when we have real try finally support.
4130 ExpectedSnippet<int> snippets[] = {
4131 {"var a = 1; try { a = 2; } finally { a = 3; }",
4132 kPointerSize,
4133 1,
4134 14,
4135 {
4136 B(LdaSmi8), U8(1), //
4137 B(Star), R(0), //
4138 B(LdaSmi8), U8(2), //
4139 B(Star), R(0), //
4140 B(LdaSmi8), U8(3), //
4141 B(Star), R(0), //
4142 B(LdaUndefined), //
4143 B(Return), //
4144 },
4145 0},
4146 {"var a = 1; try { a = 2; } catch(e) { a = 20 } finally { a = 3; }",
4147 2 * kPointerSize,
4148 1,
4149 14,
4150 {
4151 B(LdaSmi8), U8(1), //
4152 B(Star), R(0), //
4153 B(LdaSmi8), U8(2), //
4154 B(Star), R(0), //
4155 B(LdaSmi8), U8(3), //
4156 B(Star), R(0), //
4157 B(LdaUndefined), //
4158 B(Return), //
4159 },
4160 0},
4161 };
4162
4163 for (size_t i = 0; i < arraysize(snippets); i++) {
4164 Handle<BytecodeArray> bytecode_array =
4165 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
4166 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
4167 }
4168}
4169
4170
4171TEST(Throw) {
4172 InitializedHandleScope handle_scope;
4173 BytecodeGeneratorHelper helper;
4174
4175 // TODO(rmcilroy): modify tests when we have real try catch support.
4176 ExpectedSnippet<const char*> snippets[] = {
4177 {"throw 1;",
4178 0,
4179 1,
4180 3,
4181 {
4182 B(LdaSmi8), U8(1), //
4183 B(Throw), //
4184 },
4185 0},
4186 {"throw 'Error';",
4187 0,
4188 1,
4189 3,
4190 {
4191 B(LdaConstant), U8(0), //
4192 B(Throw), //
4193 },
4194 1,
4195 {"Error"}},
4196 {"var a = 1; if (a) { throw 'Error'; };",
4197 1 * kPointerSize,
4198 1,
4199 11,
4200 {
4201 B(LdaSmi8), U8(1), //
4202 B(Star), R(0), //
4203 B(JumpIfToBooleanFalse), U8(5), //
4204 B(LdaConstant), U8(0), //
4205 B(Throw), //
4206 B(LdaUndefined), //
4207 B(Return), //
4208 },
4209 1,
4210 {"Error"}},
4211 };
4212
4213 for (size_t i = 0; i < arraysize(snippets); i++) {
4214 Handle<BytecodeArray> bytecode_array =
4215 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
4216 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
4217 }
4218}
4219
4220
4221TEST(CallNew) {
4222 InitializedHandleScope handle_scope;
4223 BytecodeGeneratorHelper helper;
4224 Zone zone;
4225
4226 FeedbackVectorSpec feedback_spec(&zone);
4227 FeedbackVectorSlot slot1 = feedback_spec.AddGeneralSlot();
4228 FeedbackVectorSlot slot2 = feedback_spec.AddLoadICSlot();
4229 USE(slot1);
4230
4231 Handle<i::TypeFeedbackVector> vector =
4232 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
4233
4234 ExpectedSnippet<InstanceType> snippets[] = {
4235 {"function bar() { this.value = 0; }\n"
4236 "function f() { return new bar(); }\n"
4237 "f()",
4238 1 * kPointerSize,
4239 1,
4240 10,
4241 {
4242 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
4243 B(Star), R(0), //
4244 B(New), R(0), R(0), U8(0), //
4245 B(Return), //
4246 },
4247 1,
4248 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
4249 {"function bar(x) { this.value = 18; this.x = x;}\n"
4250 "function f() { return new bar(3); }\n"
4251 "f()",
4252 2 * kPointerSize,
4253 1,
4254 14,
4255 {
4256 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
4257 B(Star), R(0), //
4258 B(LdaSmi8), U8(3), //
4259 B(Star), R(1), //
4260 B(New), R(0), R(1), U8(1), //
4261 B(Return), //
4262 },
4263 1,
4264 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
4265 {"function bar(w, x, y, z) {\n"
4266 " this.value = 18;\n"
4267 " this.x = x;\n"
4268 " this.y = y;\n"
4269 " this.z = z;\n"
4270 "}\n"
4271 "function f() { return new bar(3, 4, 5); }\n"
4272 "f()",
4273 4 * kPointerSize,
4274 1,
4275 22,
4276 {
4277 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
4278 B(Star), R(0), //
4279 B(LdaSmi8), U8(3), //
4280 B(Star), R(1), //
4281 B(LdaSmi8), U8(4), //
4282 B(Star), R(2), //
4283 B(LdaSmi8), U8(5), //
4284 B(Star), R(3), //
4285 B(New), R(0), R(1), U8(3), //
4286 B(Return), //
4287 },
4288 1,
4289 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
4290 };
4291
4292 for (size_t i = 0; i < arraysize(snippets); i++) {
4293 Handle<BytecodeArray> bytecode_array =
4294 helper.MakeBytecode(snippets[i].code_snippet, "f");
4295 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
4296 }
4297}
4298
4299
4300TEST(ContextVariables) {
4301 InitializedHandleScope handle_scope;
4302 BytecodeGeneratorHelper helper;
4303 Zone zone;
4304
4305 FeedbackVectorSpec feedback_spec(&zone);
4306 FeedbackVectorSlot slot = feedback_spec.AddCallICSlot();
4307
4308 Handle<i::TypeFeedbackVector> vector =
4309 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
4310
4311 int closure = Register::function_closure().index();
4312 int new_target = Register::new_target().index();
4313 int first_context_slot = Context::MIN_CONTEXT_SLOTS;
4314
4315 // The wide check below relies on MIN_CONTEXT_SLOTS + 3 + 249 == 256, if this
4316 // ever changes, the REPEAT_XXX should be changed to output the correct number
4317 // of unique variables to trigger the wide slot load / store.
4318 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS + 3 + 249 == 256);
4319 int wide_slot = first_context_slot + 3;
4320
4321 ExpectedSnippet<InstanceType> snippets[] = {
4322 {"var a; return function() { a = 1; };",
4323 1 * kPointerSize,
4324 1,
4325 11,
4326 {
4327 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
4328 R(closure), U8(1), //
4329 B(PushContext), R(0), //
4330 B(CreateClosure), U8(0), U8(0), //
4331 B(Return), //
4332 },
4333 1,
4334 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
4335 {"var a = 1; return function() { a = 2; };",
4336 1 * kPointerSize,
4337 1,
4338 16,
4339 {
4340 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
4341 R(closure), U8(1), //
4342 B(PushContext), R(0), //
4343 B(LdaSmi8), U8(1), //
4344 B(StaContextSlot), R(0), U8(first_context_slot), //
4345 B(CreateClosure), U8(0), U8(0), //
4346 B(Return), //
4347 },
4348 1,
4349 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
4350 {"var a = 1; var b = 2; return function() { a = 2; b = 3 };",
4351 1 * kPointerSize,
4352 1,
4353 21,
4354 {
4355 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
4356 R(closure), U8(1), //
4357 B(PushContext), R(0), //
4358 B(LdaSmi8), U8(1), //
4359 B(StaContextSlot), R(0), U8(first_context_slot), //
4360 B(LdaSmi8), U8(2), //
4361 B(StaContextSlot), R(0), U8(first_context_slot + 1), //
4362 B(CreateClosure), U8(0), U8(0), //
4363 B(Return), //
4364 },
4365 1,
4366 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
4367 {"var a; (function() { a = 2; })(); return a;",
4368 3 * kPointerSize,
4369 1,
4370 24,
4371 {
4372 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
4373 R(closure), U8(1), //
4374 B(PushContext), R(0), //
4375 B(LdaUndefined), //
4376 B(Star), R(2), //
4377 B(CreateClosure), U8(0), U8(0), //
4378 B(Star), R(1), //
4379 B(Call), R(1), R(2), U8(0), U8(vector->GetIndex(slot)), //
4380 B(LdaContextSlot), R(0), U8(first_context_slot), //
4381 B(Return), //
4382 },
4383 1,
4384 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
4385 {"'use strict'; let a = 1; { let b = 2; return function() { a + b; }; }",
4386 4 * kPointerSize,
4387 1,
4388 44,
4389 {
4390 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
4391 R(closure), U8(1), //
4392 B(PushContext), R(0), //
4393 B(LdaTheHole), //
4394 B(StaContextSlot), R(0), U8(first_context_slot), //
4395 B(LdaSmi8), U8(1), //
4396 B(StaContextSlot), R(0), U8(first_context_slot), //
4397 B(LdaConstant), U8(0), //
4398 B(Star), R(2), //
4399 B(Ldar), R(closure), //
4400 B(Star), R(3), //
4401 B(CallRuntime), U16(Runtime::kPushBlockContext), R(2), U8(2), //
4402 B(PushContext), R(1), //
4403 B(LdaTheHole), //
4404 B(StaContextSlot), R(1), U8(first_context_slot), //
4405 B(LdaSmi8), U8(2), //
4406 B(StaContextSlot), R(1), U8(first_context_slot), //
4407 B(CreateClosure), U8(1), U8(0), //
4408 B(Return), //
4409 },
4410 2,
4411 {InstanceType::FIXED_ARRAY_TYPE,
4412 InstanceType::SHARED_FUNCTION_INFO_TYPE}},
4413 {"'use strict';\n"
4414 REPEAT_249_UNIQUE_VARS()
4415 "eval();"
4416 "var b = 100;"
4417 "return b",
4418 3 * kPointerSize,
4419 1,
4420 1041,
4421 {
4422 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
4423 U8(1), //
4424 B(PushContext), R(0), //
4425 B(Ldar), THIS(1), //
4426 B(StaContextSlot), R(0), U8(first_context_slot), //
4427 B(CreateUnmappedArguments), //
4428 B(StaContextSlot), R(0), U8(first_context_slot + 1), //
4429 B(Ldar), R(new_target), //
4430 B(StaContextSlot), R(0), U8(first_context_slot + 2), //
4431 REPEAT_249(COMMA, //
4432 B(LdaZero), //
4433 B(StaContextSlot), R(0), U8(wide_slot++)), //
4434 B(LdaUndefined), //
4435 B(Star), R(2), //
4436 B(LdaGlobalStrict), U8(0), U8(1), //
4437 B(Star), R(1), //
4438 B(Call), R(1), R(2), U8(0), U8(0), //
4439 B(LdaSmi8), U8(100), //
4440 B(StaContextSlotWide), R(0), U16(256), //
4441 B(LdaContextSlotWide), R(0), U16(256), //
4442 B(Return), //
4443 },
4444 1,
4445 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
4446 };
4447
4448 for (size_t i = 0; i < arraysize(snippets); i++) {
4449 Handle<BytecodeArray> bytecode_array =
4450 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
4451 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
4452 }
4453}
4454
4455
4456TEST(ContextParameters) {
4457 InitializedHandleScope handle_scope;
4458 BytecodeGeneratorHelper helper;
4459
4460 int closure = Register::function_closure().index();
4461 int first_context_slot = Context::MIN_CONTEXT_SLOTS;
4462
4463 ExpectedSnippet<InstanceType> snippets[] = {
4464 {"function f(arg1) { return function() { arg1 = 2; }; }",
4465 1 * kPointerSize,
4466 2,
4467 16,
4468 {
4469 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
4470 R(closure), U8(1), //
4471 B(PushContext), R(0), //
4472 B(Ldar), R(helper.kLastParamIndex), //
4473 B(StaContextSlot), R(0), U8(first_context_slot), //
4474 B(CreateClosure), U8(0), U8(0), //
4475 B(Return), //
4476 },
4477 1,
4478 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
4479 {"function f(arg1) { var a = function() { arg1 = 2; }; return arg1; }",
4480 2 * kPointerSize,
4481 2,
4482 21,
4483 {
4484 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
4485 R(closure), U8(1), //
4486 B(PushContext), R(1), //
4487 B(Ldar), R(helper.kLastParamIndex), //
4488 B(StaContextSlot), R(1), U8(first_context_slot), //
4489 B(CreateClosure), U8(0), U8(0), //
4490 B(Star), R(0), //
4491 B(LdaContextSlot), R(1), U8(first_context_slot), //
4492 B(Return), //
4493 },
4494 1,
4495 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
4496 {"function f(a1, a2, a3, a4) { return function() { a1 = a3; }; }",
4497 1 * kPointerSize,
4498 5,
4499 21,
4500 {
4501 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
4502 R(closure), U8(1), //
4503 B(PushContext), R(0), //
4504 B(Ldar), R(helper.kLastParamIndex - 3), //
4505 B(StaContextSlot), R(0), U8(first_context_slot + 1), //
4506 B(Ldar), R(helper.kLastParamIndex -1), //
4507 B(StaContextSlot), R(0), U8(first_context_slot), //
4508 B(CreateClosure), U8(0), U8(0), //
4509 B(Return), //
4510 },
4511 1,
4512 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
4513 {"function f() { var self = this; return function() { self = 2; }; }",
4514 1 * kPointerSize,
4515 1,
4516 16,
4517 {
4518 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
4519 R(closure), U8(1), //
4520 B(PushContext), R(0), //
4521 B(Ldar), R(helper.kLastParamIndex), //
4522 B(StaContextSlot), R(0), U8(first_context_slot), //
4523 B(CreateClosure), U8(0), U8(0), //
4524 B(Return), //
4525 },
4526 1,
4527 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
4528 };
4529
4530 for (size_t i = 0; i < arraysize(snippets); i++) {
4531 Handle<BytecodeArray> bytecode_array =
4532 helper.MakeBytecodeForFunction(snippets[i].code_snippet);
4533 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
4534 }
4535}
4536
4537
4538TEST(OuterContextVariables) {
4539 InitializedHandleScope handle_scope;
4540 BytecodeGeneratorHelper helper;
4541
4542 int context = Register::function_context().index();
4543 int first_context_slot = Context::MIN_CONTEXT_SLOTS;
4544
4545 ExpectedSnippet<InstanceType> snippets[] = {
4546 {"function Outer() {"
4547 " var outerVar = 1;"
4548 " function Inner(innerArg) {"
4549 " this.innerFunc = function() { return outerVar * innerArg; }"
4550 " }"
4551 " this.getInnerFunc = function() { return new Inner(1).innerFunc; }"
4552 "}"
4553 "var f = new Outer().getInnerFunc();",
4554 2 * kPointerSize,
4555 1,
4556 20,
4557 {
4558 B(Ldar), R(context), //
4559 B(Star), R(0), //
4560 B(LdaContextSlot), R(0), U8(Context::PREVIOUS_INDEX), //
4561 B(Star), R(0), //
4562 B(LdaContextSlot), R(0), U8(first_context_slot), //
4563 B(Star), R(1), //
4564 B(LdaContextSlot), R(context), U8(first_context_slot), //
4565 B(Mul), R(1), //
4566 B(Return), //
4567 }},
4568 {"function Outer() {"
4569 " var outerVar = 1;"
4570 " function Inner(innerArg) {"
4571 " this.innerFunc = function() { outerVar = innerArg; }"
4572 " }"
4573 " this.getInnerFunc = function() { return new Inner(1).innerFunc; }"
4574 "}"
4575 "var f = new Outer().getInnerFunc();",
4576 2 * kPointerSize,
4577 1,
4578 21,
4579 {
4580 B(LdaContextSlot), R(context), U8(first_context_slot), //
4581 B(Star), R(0), //
4582 B(Ldar), R(context), //
4583 B(Star), R(1), //
4584 B(LdaContextSlot), R(1), U8(Context::PREVIOUS_INDEX), //
4585 B(Star), R(1), //
4586 B(Ldar), R(0), //
4587 B(StaContextSlot), R(1), U8(first_context_slot), //
4588 B(LdaUndefined), //
4589 B(Return), //
4590 }},
4591 };
4592
4593 for (size_t i = 0; i < arraysize(snippets); i++) {
4594 Handle<BytecodeArray> bytecode_array =
4595 helper.MakeBytecodeForFunctionNoFilter(snippets[i].code_snippet);
4596 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
4597 }
4598}
4599
4600
4601TEST(CountOperators) {
4602 InitializedHandleScope handle_scope;
4603 BytecodeGeneratorHelper helper;
4604 Zone zone;
4605
4606 FeedbackVectorSpec feedback_spec(&zone);
4607 FeedbackVectorSlot slot1 = feedback_spec.AddLoadICSlot();
4608 FeedbackVectorSlot slot2 = feedback_spec.AddStoreICSlot();
4609 Handle<i::TypeFeedbackVector> vector =
4610 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
4611
4612 FeedbackVectorSpec store_feedback_spec(&zone);
4613 FeedbackVectorSlot store_slot = store_feedback_spec.AddStoreICSlot();
4614 Handle<i::TypeFeedbackVector> store_vector =
4615 i::NewTypeFeedbackVector(helper.isolate(), &store_feedback_spec);
4616
4617 int closure = Register::function_closure().index();
4618 int first_context_slot = Context::MIN_CONTEXT_SLOTS;
4619
4620 int object_literal_flags =
4621 ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos;
4622 int array_literal_flags =
4623 ArrayLiteral::kDisableMementos | ArrayLiteral::kShallowElements;
4624
4625 ExpectedSnippet<InstanceType> snippets[] = {
4626 {"var a = 1; return ++a;",
4627 1 * kPointerSize,
4628 1,
4629 9,
4630 {
4631 B(LdaSmi8), U8(1), //
4632 B(Star), R(0), //
4633 B(ToNumber), //
4634 B(Inc), //
4635 B(Star), R(0), //
4636 B(Return), //
4637 }},
4638 {"var a = 1; return a++;",
4639 2 * kPointerSize,
4640 1,
4641 13,
4642 {
4643 B(LdaSmi8), U8(1), //
4644 B(Star), R(0), //
4645 B(ToNumber), //
4646 B(Star), R(1), //
4647 B(Inc), //
4648 B(Star), R(0), //
4649 B(Ldar), R(1), //
4650 B(Return), //
4651 }},
4652 {"var a = 1; return --a;",
4653 1 * kPointerSize,
4654 1,
4655 9,
4656 {
4657 B(LdaSmi8), U8(1), //
4658 B(Star), R(0), //
4659 B(ToNumber), //
4660 B(Dec), //
4661 B(Star), R(0), //
4662 B(Return), //
4663 }},
4664 {"var a = 1; return a--;",
4665 2 * kPointerSize,
4666 1,
4667 13,
4668 {
4669 B(LdaSmi8), U8(1), //
4670 B(Star), R(0), //
4671 B(ToNumber), //
4672 B(Star), R(1), //
4673 B(Dec), //
4674 B(Star), R(0), //
4675 B(Ldar), R(1), //
4676 B(Return), //
4677 }},
4678 {"var a = { val: 1 }; return a.val++;",
4679 3 * kPointerSize,
4680 1,
4681 23,
4682 {
4683 B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags), //
4684 B(Star), R(0), //
4685 B(Star), R(1), //
4686 B(LoadICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), //
4687 B(ToNumber), //
4688 B(Star), R(2), //
4689 B(Inc), //
4690 B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot2)), //
4691 B(Ldar), R(2), //
4692 B(Return), //
4693 },
4694 2,
4695 {InstanceType::FIXED_ARRAY_TYPE,
4696 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
4697 {"var a = { val: 1 }; return --a.val;",
4698 2 * kPointerSize,
4699 1,
4700 19,
4701 {
4702 B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags), //
4703 B(Star), R(0), //
4704 B(Star), R(1), //
4705 B(LoadICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), //
4706 B(ToNumber), //
4707 B(Dec), //
4708 B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot2)), //
4709 B(Return), //
4710 },
4711 2,
4712 {InstanceType::FIXED_ARRAY_TYPE,
4713 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
4714 {"var name = 'var'; var a = { val: 1 }; return a[name]--;",
4715 5 * kPointerSize,
4716 1,
4717 30,
4718 {
4719 B(LdaConstant), U8(0), //
4720 B(Star), R(0), //
4721 B(CreateObjectLiteral), U8(1), U8(0), U8(object_literal_flags), //
4722 B(Star), R(1), //
4723 B(Star), R(2), //
4724 B(Ldar), R(0), //
4725 B(Star), R(3), //
4726 B(KeyedLoadICSloppy), R(2), U8(vector->GetIndex(slot1)), //
4727 B(ToNumber), //
4728 B(Star), R(4), //
4729 B(Dec), //
4730 B(KeyedStoreICSloppy), R(2), R(3), U8(vector->GetIndex(slot2)), //
4731 B(Ldar), R(4), //
4732 B(Return), //
4733 },
4734 2,
4735 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
4736 InstanceType::FIXED_ARRAY_TYPE}},
4737 {"var name = 'var'; var a = { val: 1 }; return ++a[name];",
4738 4 * kPointerSize,
4739 1,
4740 26,
4741 {
4742 B(LdaConstant), U8(0), //
4743 B(Star), R(0), //
4744 B(CreateObjectLiteral), U8(1), U8(0), U8(object_literal_flags), //
4745 B(Star), R(1), //
4746 B(Star), R(2), //
4747 B(Ldar), R(0), //
4748 B(Star), R(3), //
4749 B(KeyedLoadICSloppy), R(2), U8(vector->GetIndex(slot1)), //
4750 B(ToNumber), //
4751 B(Inc), //
4752 B(KeyedStoreICSloppy), R(2), R(3), U8(vector->GetIndex(slot2)), //
4753 B(Return), //
4754 },
4755 2,
4756 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
4757 InstanceType::FIXED_ARRAY_TYPE}},
4758 {"var a = 1; var b = function() { return a }; return ++a;",
4759 2 * kPointerSize,
4760 1,
4761 26,
4762 {
4763 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
4764 U8(1), //
4765 B(PushContext), R(1), //
4766 B(LdaSmi8), U8(1), //
4767 B(StaContextSlot), R(1), U8(first_context_slot), //
4768 B(CreateClosure), U8(0), U8(0), //
4769 B(Star), R(0), //
4770 B(LdaContextSlot), R(1), U8(first_context_slot), //
4771 B(ToNumber), //
4772 B(Inc), //
4773 B(StaContextSlot), R(1), U8(first_context_slot), //
4774 B(Return), //
4775 },
4776 1,
4777 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
4778 {"var a = 1; var b = function() { return a }; return a--;",
4779 3 * kPointerSize,
4780 1,
4781 30,
4782 {
4783 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
4784 U8(1), //
4785 B(PushContext), R(1), //
4786 B(LdaSmi8), U8(1), //
4787 B(StaContextSlot), R(1), U8(first_context_slot), //
4788 B(CreateClosure), U8(0), U8(0), //
4789 B(Star), R(0), //
4790 B(LdaContextSlot), R(1), U8(first_context_slot), //
4791 B(ToNumber), //
4792 B(Star), R(2), //
4793 B(Dec), //
4794 B(StaContextSlot), R(1), U8(first_context_slot), //
4795 B(Ldar), R(2), //
4796 B(Return), //
4797 },
4798 1,
4799 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
4800 {"var idx = 1; var a = [1, 2]; return a[idx++] = 2;",
4801 4 * kPointerSize,
4802 1,
4803 27,
4804 {
4805 B(LdaSmi8), U8(1), //
4806 B(Star), R(0), //
4807 B(CreateArrayLiteral), U8(0), U8(0), U8(array_literal_flags), //
4808 B(Star), R(1), //
4809 B(Star), R(2), //
4810 B(Ldar), R(0), //
4811 B(ToNumber), //
4812 B(Star), R(3), //
4813 B(Inc), //
4814 B(Star), R(0), //
4815 B(LdaSmi8), U8(2), //
4816 B(KeyedStoreICSloppy), R(2), R(3), //
4817 U8(store_vector->GetIndex(store_slot)), //
4818 B(Return), //
4819 },
4820 1,
4821 {InstanceType::FIXED_ARRAY_TYPE}},
4822 };
4823
4824 for (size_t i = 0; i < arraysize(snippets); i++) {
4825 Handle<BytecodeArray> bytecode_array =
4826 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
4827 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
4828 }
4829}
4830
4831
4832TEST(GlobalCountOperators) {
4833 InitializedHandleScope handle_scope;
4834 BytecodeGeneratorHelper helper;
4835 Zone zone;
4836
4837 FeedbackVectorSpec feedback_spec(&zone);
4838 FeedbackVectorSlot slot1 = feedback_spec.AddLoadICSlot();
4839 FeedbackVectorSlot slot2 = feedback_spec.AddStoreICSlot();
4840
4841 Handle<i::TypeFeedbackVector> vector =
4842 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
4843
4844 ExpectedSnippet<const char*> snippets[] = {
4845 {"var global = 1;\nfunction f() { return ++global; }\nf()",
4846 0,
4847 1,
4848 9,
4849 {
4850 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot1)), //
4851 B(ToNumber), //
4852 B(Inc), //
4853 B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
4854 B(Return), //
4855 },
4856 1,
4857 {"global"}},
4858 {"var global = 1;\nfunction f() { return global--; }\nf()",
4859 1 * kPointerSize,
4860 1,
4861 13,
4862 {
4863 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot1)), //
4864 B(ToNumber), //
4865 B(Star), R(0), //
4866 B(Dec), //
4867 B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
4868 B(Ldar), R(0), //
4869 B(Return),
4870 },
4871 1,
4872 {"global"}},
4873 {"unallocated = 1;\nfunction f() { 'use strict'; return --unallocated; }"
4874 "f()",
4875 0,
4876 1,
4877 9,
4878 {
4879 B(LdaGlobalStrict), U8(0), U8(vector->GetIndex(slot1)), //
4880 B(ToNumber), //
4881 B(Dec), //
4882 B(StaGlobalStrict), U8(0), U8(vector->GetIndex(slot2)), //
4883 B(Return), //
4884 },
4885 1,
4886 {"unallocated"}},
4887 {"unallocated = 1;\nfunction f() { return unallocated++; }\nf()",
4888 1 * kPointerSize,
4889 1,
4890 13,
4891 {
4892 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot1)), //
4893 B(ToNumber), //
4894 B(Star), R(0), //
4895 B(Inc), //
4896 B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
4897 B(Ldar), R(0), //
4898 B(Return),
4899 },
4900 1,
4901 {"unallocated"}},
4902 };
4903
4904 for (size_t i = 0; i < arraysize(snippets); i++) {
4905 Handle<BytecodeArray> bytecode_array =
4906 helper.MakeBytecode(snippets[i].code_snippet, "f");
4907 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
4908 }
4909}
4910
4911
4912TEST(CompoundExpressions) {
4913 InitializedHandleScope handle_scope;
4914 BytecodeGeneratorHelper helper;
4915 Zone zone;
4916
4917 int closure = Register::function_closure().index();
4918 int first_context_slot = Context::MIN_CONTEXT_SLOTS;
4919
4920 FeedbackVectorSpec feedback_spec(&zone);
4921 FeedbackVectorSlot slot1 = feedback_spec.AddLoadICSlot();
4922 FeedbackVectorSlot slot2 = feedback_spec.AddStoreICSlot();
4923
4924 Handle<i::TypeFeedbackVector> vector =
4925 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
4926
4927 int object_literal_flags =
4928 ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos;
4929 ExpectedSnippet<InstanceType> snippets[] = {
4930 {"var a = 1; a += 2;",
4931 2 * kPointerSize,
4932 1,
4933 14,
4934 {
4935 B(LdaSmi8), U8(1), //
4936 B(Star), R(0), //
4937 B(Star), R(1), //
4938 B(LdaSmi8), U8(2), //
4939 B(Add), R(1), //
4940 B(Star), R(0), //
4941 B(LdaUndefined), //
4942 B(Return), //
4943 }},
4944 {"var a = 1; a /= 2;",
4945 2 * kPointerSize,
4946 1,
4947 14,
4948 {
4949 B(LdaSmi8), U8(1), //
4950 B(Star), R(0), //
4951 B(Star), R(1), //
4952 B(LdaSmi8), U8(2), //
4953 B(Div), R(1), //
4954 B(Star), R(0), //
4955 B(LdaUndefined), //
4956 B(Return), //
4957 }},
4958 {"var a = { val: 2 }; a.name *= 2;",
4959 3 * kPointerSize,
4960 1,
4961 24,
4962 {
4963 B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags), //
4964 B(Star), R(0), //
4965 B(Star), R(1), //
4966 B(LoadICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), //
4967 B(Star), R(2), //
4968 B(LdaSmi8), U8(2), //
4969 B(Mul), R(2), //
4970 B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot2)), //
4971 B(LdaUndefined), //
4972 B(Return), //
4973 },
4974 2,
4975 {InstanceType::FIXED_ARRAY_TYPE,
4976 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
4977 {"var a = { 1: 2 }; a[1] ^= 2;",
4978 4 * kPointerSize,
4979 1,
4980 27,
4981 {
4982 B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags), //
4983 B(Star), R(0), //
4984 B(Star), R(1), //
4985 B(LdaSmi8), U8(1), //
4986 B(Star), R(2), //
4987 B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot1)), //
4988 B(Star), R(3), //
4989 B(LdaSmi8), U8(2), //
4990 B(BitwiseXor), R(3), //
4991 B(KeyedStoreICSloppy), R(1), R(2), U8(vector->GetIndex(slot2)), //
4992 B(LdaUndefined), //
4993 B(Return), //
4994 },
4995 1,
4996 {InstanceType::FIXED_ARRAY_TYPE}},
4997 {"var a = 1; (function f() { return a; }); a |= 24;",
4998 2 * kPointerSize,
4999 1,
5000 29,
5001 {
5002 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
5003 U8(1), //
5004 B(PushContext), R(0), //
5005 B(LdaSmi8), U8(1), //
5006 B(StaContextSlot), R(0), U8(first_context_slot), //
5007 B(CreateClosure), U8(0), U8(0), //
5008 B(LdaContextSlot), R(0), U8(first_context_slot), //
5009 B(Star), R(1), //
5010 B(LdaSmi8), U8(24), //
5011 B(BitwiseOr), R(1), //
5012 B(StaContextSlot), R(0), U8(first_context_slot), //
5013 B(LdaUndefined), //
5014 B(Return), //
5015 },
5016 1,
5017 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
5018 };
5019
5020 for (size_t i = 0; i < arraysize(snippets); i++) {
5021 Handle<BytecodeArray> bytecode_array =
5022 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
5023 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
5024 }
5025}
5026
5027
5028TEST(GlobalCompoundExpressions) {
5029 InitializedHandleScope handle_scope;
5030 BytecodeGeneratorHelper helper;
5031 Zone zone;
5032
5033 FeedbackVectorSpec feedback_spec(&zone);
5034 FeedbackVectorSlot slot1 = feedback_spec.AddLoadICSlot();
5035 FeedbackVectorSlot slot2 = feedback_spec.AddStoreICSlot();
5036
5037 Handle<i::TypeFeedbackVector> vector =
5038 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
5039
5040 ExpectedSnippet<const char*> snippets[] = {
5041 {"var global = 1;\nfunction f() { return global &= 1; }\nf()",
5042 1 * kPointerSize,
5043 1,
5044 13,
5045 {
5046 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot1)), //
5047 B(Star), R(0), //
5048 B(LdaSmi8), U8(1), //
5049 B(BitwiseAnd), R(0), //
5050 B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
5051 B(Return), //
5052 },
5053 1,
5054 {"global"}},
5055 {"unallocated = 1;\nfunction f() { return unallocated += 1; }\nf()",
5056 1 * kPointerSize,
5057 1,
5058 13,
5059 {
5060 B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot1)), //
5061 B(Star), R(0), //
5062 B(LdaSmi8), U8(1), //
5063 B(Add), R(0), //
5064 B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
5065 B(Return), //
5066 },
5067 1,
5068 {"unallocated"}},
5069 };
5070
5071 for (size_t i = 0; i < arraysize(snippets); i++) {
5072 Handle<BytecodeArray> bytecode_array =
5073 helper.MakeBytecode(snippets[i].code_snippet, "f");
5074 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
5075 }
5076}
5077
5078
5079TEST(CreateArguments) {
5080 InitializedHandleScope handle_scope;
5081 BytecodeGeneratorHelper helper;
5082 Zone zone;
5083
5084 int closure = Register::function_closure().index();
5085 int first_context_slot = Context::MIN_CONTEXT_SLOTS;
5086
5087 FeedbackVectorSpec feedback_spec(&zone);
5088 FeedbackVectorSlot slot = feedback_spec.AddKeyedLoadICSlot();
5089
5090 Handle<i::TypeFeedbackVector> vector =
5091 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
5092
5093 ExpectedSnippet<const char*> snippets[] = {
5094 {"function f() { return arguments; }",
5095 1 * kPointerSize,
5096 1,
5097 4,
5098 {
5099 B(CreateMappedArguments), //
5100 B(Star), R(0), //
5101 B(Return), //
5102 }},
5103 {"function f() { return arguments[0]; }",
5104 2 * kPointerSize,
5105 1,
5106 10,
5107 {
5108 B(CreateMappedArguments), //
5109 B(Star), R(0), //
5110 B(Star), R(1), //
5111 B(LdaZero), //
5112 B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot)), //
5113 B(Return), //
5114 }},
5115 {"function f() { 'use strict'; return arguments; }",
5116 1 * kPointerSize,
5117 1,
5118 4,
5119 {
5120 B(CreateUnmappedArguments), //
5121 B(Star), R(0), //
5122 B(Return), //
5123 }},
5124 {"function f(a) { return arguments[0]; }",
5125 3 * kPointerSize,
5126 2,
5127 22,
5128 {
5129 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
5130 U8(1), //
5131 B(PushContext), R(1), //
5132 B(Ldar), R(BytecodeGeneratorHelper::kLastParamIndex), //
5133 B(StaContextSlot), R(1), U8(first_context_slot), //
5134 B(CreateMappedArguments), //
5135 B(Star), R(0), //
5136 B(Star), R(2), //
5137 B(LdaZero), //
5138 B(KeyedLoadICSloppy), R(2), U8(vector->GetIndex(slot)), //
5139 B(Return), //
5140 }},
5141 {"function f(a, b, c) { return arguments; }",
5142 2 * kPointerSize,
5143 4,
5144 26,
5145 {
5146 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
5147 U8(1), //
5148 B(PushContext), R(1), //
5149 B(Ldar), R(BytecodeGeneratorHelper::kLastParamIndex - 2), //
5150 B(StaContextSlot), R(1), U8(first_context_slot + 2), //
5151 B(Ldar), R(BytecodeGeneratorHelper::kLastParamIndex - 1), //
5152 B(StaContextSlot), R(1), U8(first_context_slot + 1), //
5153 B(Ldar), R(BytecodeGeneratorHelper::kLastParamIndex), //
5154 B(StaContextSlot), R(1), U8(first_context_slot), //
5155 B(CreateMappedArguments), //
5156 B(Star), R(0), //
5157 B(Return), //
5158 }},
5159 {"function f(a, b, c) { 'use strict'; return arguments; }",
5160 1 * kPointerSize,
5161 4,
5162 4,
5163 {
5164 B(CreateUnmappedArguments), //
5165 B(Star), R(0), //
5166 B(Return), //
5167 }},
5168 };
5169
5170 for (size_t i = 0; i < arraysize(snippets); i++) {
5171 Handle<BytecodeArray> bytecode_array =
5172 helper.MakeBytecodeForFunction(snippets[i].code_snippet);
5173 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
5174 }
5175}
5176
5177
5178TEST(IllegalRedeclaration) {
5179 InitializedHandleScope handle_scope;
5180 BytecodeGeneratorHelper helper;
5181
5182 CHECK_GE(MessageTemplate::kVarRedeclaration, 128);
5183 // Must adapt bytecode if this changes.
5184
5185 ExpectedSnippet<Handle<Object>, 2> snippets[] = {
5186 {"const a = 1; { var a = 2; }",
5187 3 * kPointerSize,
5188 1,
5189 14,
5190 {
5191 B(LdaConstant), U8(0), //
5192 B(Star), R(1), //
5193 B(LdaConstant), U8(1), //
5194 B(Star), R(2), //
5195 B(CallRuntime), U16(Runtime::kNewSyntaxError), R(1), U8(2), //
5196 B(Throw), //
5197 },
5198 2,
5199 {helper.factory()->NewNumberFromInt(MessageTemplate::kVarRedeclaration),
5200 helper.factory()->NewStringFromAsciiChecked("a")}},
5201 };
5202
5203 for (size_t i = 0; i < arraysize(snippets); i++) {
5204 Handle<BytecodeArray> bytecode_array =
5205 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
5206 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
5207 }
5208}
5209
5210
5211TEST(ForIn) {
5212 InitializedHandleScope handle_scope;
5213 BytecodeGeneratorHelper helper;
5214 Zone zone;
5215
5216 int simple_flags =
5217 ArrayLiteral::kDisableMementos | ArrayLiteral::kShallowElements;
5218 int deep_elements_flags =
5219 ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos;
5220
5221 FeedbackVectorSpec feedback_spec(&zone);
5222 feedback_spec.AddStoreICSlot();
5223 FeedbackVectorSlot slot2 = feedback_spec.AddStoreICSlot();
5224 FeedbackVectorSlot slot3 = feedback_spec.AddStoreICSlot();
5225 FeedbackVectorSlot slot4 = feedback_spec.AddStoreICSlot();
5226 Handle<i::TypeFeedbackVector> vector =
5227 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
5228
5229 ExpectedSnippet<InstanceType> snippets[] = {
5230 {"for (var p in null) {}",
5231 2 * kPointerSize,
5232 1,
5233 2,
5234 {B(LdaUndefined), B(Return)},
5235 0},
5236 {"for (var p in undefined) {}",
5237 2 * kPointerSize,
5238 1,
5239 2,
5240 {B(LdaUndefined), B(Return)},
5241 0},
5242 {"for (var p in undefined) {}",
5243 2 * kPointerSize,
5244 1,
5245 2,
5246 {B(LdaUndefined), B(Return)},
5247 0},
5248 {"var x = 'potatoes';\n"
5249 "for (var p in x) { return p; }",
5250 8 * kPointerSize,
5251 1,
5252 45,
5253 {
5254 B(LdaConstant), U8(0), //
5255 B(Star), R(1), //
5256 B(JumpIfUndefined), U8(39), //
5257 B(JumpIfNull), U8(37), //
5258 B(ToObject), //
5259 B(JumpIfNull), U8(34), //
5260 B(Star), R(3), //
5261 B(ForInPrepare), R(4), R(5), R(6), //
5262 B(LdaZero), //
5263 B(Star), R(7), //
5264 B(ForInDone), R(7), R(6), //
5265 B(JumpIfTrue), U8(20), //
5266 B(ForInNext), R(3), R(4), R(5), R(7), //
5267 B(JumpIfUndefined), U8(7), //
5268 B(Star), R(0), //
5269 B(Star), R(2), //
5270 B(Return), //
5271 B(ForInStep), R(7), //
5272 B(Star), R(7), //
5273 B(Jump), U8(-21), //
5274 B(LdaUndefined), //
5275 B(Return), //
5276 },
5277 1,
5278 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
5279 {"var x = 0;\n"
5280 "for (var p in [1,2,3]) { x += p; }",
5281 9 * kPointerSize,
5282 1,
5283 57,
5284 {
5285 B(LdaZero), //
5286 B(Star), R(1), //
5287 B(CreateArrayLiteral), U8(0), U8(0), U8(3), //
5288 B(JumpIfUndefined), U8(48), //
5289 B(JumpIfNull), U8(46), //
5290 B(ToObject), //
5291 B(JumpIfNull), U8(43), //
5292 B(Star), R(3), //
5293 B(ForInPrepare), R(4), R(5), R(6), //
5294 B(LdaZero), //
5295 B(Star), R(7), //
5296 B(ForInDone), R(7), R(6), //
5297 B(JumpIfTrue), U8(29), //
5298 B(ForInNext), R(3), R(4), R(5), R(7), //
5299 B(JumpIfUndefined), U8(16), //
5300 B(Star), R(0), //
5301 B(Star), R(2), //
5302 B(Ldar), R(1), //
5303 B(Star), R(8), //
5304 B(Ldar), R(2), //
5305 B(Add), R(8), //
5306 B(Star), R(1), //
5307 B(ForInStep), R(7), //
5308 B(Star), R(7), //
5309 B(Jump), U8(-30), //
5310 B(LdaUndefined), //
5311 B(Return), //
5312 },
5313 1,
5314 {InstanceType::FIXED_ARRAY_TYPE}},
5315 {"var x = { 'a': 1, 'b': 2 };\n"
5316 "for (x['a'] in [10, 20, 30]) {\n"
5317 " if (x['a'] == 10) continue;\n"
5318 " if (x['a'] == 20) break;\n"
5319 "}",
5320 8 * kPointerSize,
5321 1,
5322 94,
5323 {
5324 B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
5325 B(Star), R(0), //
5326 B(CreateArrayLiteral), U8(1), U8(1), U8(simple_flags), //
5327 B(JumpIfUndefined), U8(82), //
5328 B(JumpIfNull), U8(80), //
5329 B(ToObject), //
5330 B(JumpIfNull), U8(77), //
5331 B(Star), R(1), //
5332 B(ForInPrepare), R(2), R(3), R(4), //
5333 B(LdaZero), //
5334 B(Star), R(5), //
5335 B(ForInDone), R(5), R(4), //
5336 B(JumpIfTrue), U8(63), //
5337 B(ForInNext), R(1), R(2), R(3), R(5), //
5338 B(JumpIfUndefined), U8(50), //
5339 B(Star), R(6), //
5340 B(Ldar), R(0), //
5341 B(Star), R(7), //
5342 B(Ldar), R(6), //
5343 B(StoreICSloppy), R(7), U8(2), U8(vector->GetIndex(slot4)), //
5344 B(Ldar), R(0), //
5345 B(Star), R(6), //
5346 B(LoadICSloppy), R(6), U8(2), U8(vector->GetIndex(slot2)), //
5347 B(Star), R(7), //
5348 B(LdaSmi8), U8(10), //
5349 B(TestEqual), R(7), //
5350 B(JumpIfFalse), U8(4), //
5351 B(Jump), U8(20), //
5352 B(Ldar), R(0), //
5353 B(Star), R(6), //
5354 B(LoadICSloppy), R(6), U8(2), U8(vector->GetIndex(slot3)), //
5355 B(Star), R(7), //
5356 B(LdaSmi8), U8(20), //
5357 B(TestEqual), R(7), //
5358 B(JumpIfFalse), U8(4), //
5359 B(Jump), U8(8), //
5360 B(ForInStep), R(5), //
5361 B(Star), R(5), //
5362 B(Jump), U8(-64), //
5363 B(LdaUndefined), //
5364 B(Return), //
5365 },
5366 3,
5367 {InstanceType::FIXED_ARRAY_TYPE, InstanceType::FIXED_ARRAY_TYPE,
5368 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
5369 {"var x = [ 10, 11, 12 ] ;\n"
5370 "for (x[0] in [1,2,3]) { return x[3]; }",
5371 9 * kPointerSize,
5372 1,
5373 71,
5374 {
5375 B(CreateArrayLiteral), U8(0), U8(0), U8(simple_flags), //
5376 B(Star), R(0), //
5377 B(CreateArrayLiteral), U8(1), U8(1), U8(simple_flags), //
5378 B(JumpIfUndefined), U8(59), //
5379 B(JumpIfNull), U8(57), //
5380 B(ToObject), //
5381 B(JumpIfNull), U8(54), //
5382 B(Star), R(1), //
5383 B(ForInPrepare), R(2), R(3), R(4), //
5384 B(LdaZero), //
5385 B(Star), R(5), //
5386 B(ForInDone), R(5), R(4), //
5387 B(JumpIfTrue), U8(40), //
5388 B(ForInNext), R(1), R(2), R(3), R(5), //
5389 B(JumpIfUndefined), U8(27), //
5390 B(Star), R(6), //
5391 B(Ldar), R(0), //
5392 B(Star), R(7), //
5393 B(LdaZero), //
5394 B(Star), R(8), //
5395 B(Ldar), R(6), //
5396 B(KeyedStoreICSloppy), R(7), R(8), U8(vector->GetIndex(slot3)), //
5397 B(Ldar), R(0), //
5398 B(Star), R(6), //
5399 B(LdaSmi8), U8(3), //
5400 B(KeyedLoadICSloppy), R(6), U8(vector->GetIndex(slot2)), //
5401 B(Return), //
5402 B(ForInStep), R(5), //
5403 B(Star), R(5), //
5404 B(Jump), U8(-41), //
5405 B(LdaUndefined), //
5406 B(Return), //
5407 },
5408 2,
5409 {InstanceType::FIXED_ARRAY_TYPE, InstanceType::FIXED_ARRAY_TYPE}},
5410 };
5411
5412 for (size_t i = 0; i < arraysize(snippets); i++) {
5413 Handle<BytecodeArray> bytecode_array =
5414 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
5415 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
5416 }
5417}
5418
5419
5420TEST(Conditional) {
5421 InitializedHandleScope handle_scope;
5422 BytecodeGeneratorHelper helper;
5423
5424 ExpectedSnippet<int> snippets[] = {
5425 {"return 1 ? 2 : 3;",
5426 0,
5427 1,
5428 11,
5429 {
5430 B(LdaSmi8), U8(1), //
5431 B(JumpIfToBooleanFalse), U8(6), //
5432 B(LdaSmi8), U8(2), //
5433 B(Jump), U8(4), //
5434 B(LdaSmi8), U8(3), //
5435 B(Return), //
5436 }},
5437 {"return 1 ? 2 ? 3 : 4 : 5;",
5438 0,
5439 1,
5440 19,
5441 {
5442 B(LdaSmi8), U8(1), //
5443 B(JumpIfToBooleanFalse), U8(14), //
5444 B(LdaSmi8), U8(2), //
5445 B(JumpIfToBooleanFalse), U8(6), //
5446 B(LdaSmi8), U8(3), //
5447 B(Jump), U8(4), //
5448 B(LdaSmi8), U8(4), //
5449 B(Jump), U8(4), //
5450 B(LdaSmi8), U8(5), //
5451 B(Return), //
5452 }},
5453 };
5454
5455 for (size_t i = 0; i < arraysize(snippets); i++) {
5456 Handle<BytecodeArray> bytecode_array =
5457 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
5458 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
5459 }
5460}
5461
5462
5463TEST(Switch) {
5464 InitializedHandleScope handle_scope;
5465 BytecodeGeneratorHelper helper;
5466
5467 ExpectedSnippet<int> snippets[] = {
5468 {"var a = 1;\n"
5469 "switch(a) {\n"
5470 " case 1: return 2;\n"
5471 " case 2: return 3;\n"
5472 "}\n",
5473 3 * kPointerSize,
5474 1,
5475 30,
5476 {
5477 B(LdaSmi8), U8(1), //
5478 B(Star), R(1), // The tag variable is allocated as a
5479 B(Star), R(0), // local by the parser, hence the store
5480 B(Star), R(2), // to another local register.
5481 B(LdaSmi8), U8(1), //
5482 B(TestEqualStrict), R(2), //
5483 B(JumpIfTrue), U8(10), //
5484 B(LdaSmi8), U8(2), //
5485 B(TestEqualStrict), R(2), //
5486 B(JumpIfTrue), U8(7), //
5487 B(Jump), U8(8), //
5488 B(LdaSmi8), U8(2), //
5489 B(Return), //
5490 B(LdaSmi8), U8(3), //
5491 B(Return), //
5492 B(LdaUndefined), //
5493 B(Return), //
5494 }},
5495 {"var a = 1;\n"
5496 "switch(a) {\n"
5497 " case 1: a = 2; break;\n"
5498 " case 2: a = 3; break;\n"
5499 "}\n",
5500 3 * kPointerSize,
5501 1,
5502 36,
5503 {
5504 B(LdaSmi8), U8(1), //
5505 B(Star), R(1), //
5506 B(Star), R(0), //
5507 B(Star), R(2), //
5508 B(LdaSmi8), U8(1), //
5509 B(TestEqualStrict), R(2), //
5510 B(JumpIfTrue), U8(10), //
5511 B(LdaSmi8), U8(2), //
5512 B(TestEqualStrict), R(2), //
5513 B(JumpIfTrue), U8(10), //
5514 B(Jump), U8(14), //
5515 B(LdaSmi8), U8(2), //
5516 B(Star), R(1), //
5517 B(Jump), U8(8), //
5518 B(LdaSmi8), U8(3), //
5519 B(Star), R(1), //
5520 B(Jump), U8(2), //
5521 B(LdaUndefined), //
5522 B(Return), //
5523 }},
5524 {"var a = 1;\n"
5525 "switch(a) {\n"
5526 " case 1: a = 2; // fall-through\n"
5527 " case 2: a = 3; break;\n"
5528 "}\n",
5529 3 * kPointerSize,
5530 1,
5531 34,
5532 {
5533 B(LdaSmi8), U8(1), //
5534 B(Star), R(1), //
5535 B(Star), R(0), //
5536 B(Star), R(2), //
5537 B(LdaSmi8), U8(1), //
5538 B(TestEqualStrict), R(2), //
5539 B(JumpIfTrue), U8(10), //
5540 B(LdaSmi8), U8(2), //
5541 B(TestEqualStrict), R(2), //
5542 B(JumpIfTrue), U8(8), //
5543 B(Jump), U8(12), //
5544 B(LdaSmi8), U8(2), //
5545 B(Star), R(1), //
5546 B(LdaSmi8), U8(3), //
5547 B(Star), R(1), //
5548 B(Jump), U8(2), //
5549 B(LdaUndefined), //
5550 B(Return), //
5551 }},
5552 {"var a = 1;\n"
5553 "switch(a) {\n"
5554 " case 2: break;\n"
5555 " case 3: break;\n"
5556 " default: a = 1; break;\n"
5557 "}\n",
5558 3 * kPointerSize,
5559 1,
5560 34,
5561 {
5562 B(LdaSmi8), U8(1), //
5563 B(Star), R(1), //
5564 B(Star), R(0), //
5565 B(Star), R(2), //
5566 B(LdaSmi8), U8(2), //
5567 B(TestEqualStrict), R(2), //
5568 B(JumpIfTrue), U8(10), //
5569 B(LdaSmi8), U8(3), //
5570 B(TestEqualStrict), R(2), //
5571 B(JumpIfTrue), U8(6), //
5572 B(Jump), U8(6), //
5573 B(Jump), U8(10), //
5574 B(Jump), U8(8), //
5575 B(LdaSmi8), U8(1), //
5576 B(Star), R(1), //
5577 B(Jump), U8(2), //
5578 B(LdaUndefined), //
5579 B(Return), //
5580 }},
5581 {"var a = 1;\n"
5582 "switch(typeof(a)) {\n"
5583 " case 2: a = 1; break;\n"
5584 " case 3: a = 2; break;\n"
5585 " default: a = 3; break;\n"
5586 "}\n",
5587 3 * kPointerSize,
5588 1,
5589 43,
5590 {
5591 B(LdaSmi8), U8(1), //
5592 B(Star), R(1), //
5593 B(TypeOf), //
5594 B(Star), R(0), //
5595 B(Star), R(2), //
5596 B(LdaSmi8), U8(2), //
5597 B(TestEqualStrict), R(2), //
5598 B(JumpIfTrue), U8(10), //
5599 B(LdaSmi8), U8(3), //
5600 B(TestEqualStrict), R(2), //
5601 B(JumpIfTrue), U8(10), //
5602 B(Jump), U8(14), //
5603 B(LdaSmi8), U8(1), //
5604 B(Star), R(1), //
5605 B(Jump), U8(14), //
5606 B(LdaSmi8), U8(2), //
5607 B(Star), R(1), //
5608 B(Jump), U8(8), //
5609 B(LdaSmi8), U8(3), //
5610 B(Star), R(1), //
5611 B(Jump), U8(2), //
5612 B(LdaUndefined), //
5613 B(Return), //
5614 }},
5615 {"var a = 1;\n"
5616 "switch(a) {\n"
5617 " case typeof(a): a = 1; break;\n"
5618 " default: a = 2; break;\n"
5619 "}\n",
5620 3 * kPointerSize,
5621 1,
5622 31,
5623 {
5624 B(LdaSmi8), U8(1), //
5625 B(Star), R(1), //
5626 B(Star), R(0), //
5627 B(Star), R(2), //
5628 B(Ldar), R(1), //
5629 B(TypeOf), //
5630 B(TestEqualStrict), R(2), //
5631 B(JumpIfTrue), U8(4), //
5632 B(Jump), U8(8), //
5633 B(LdaSmi8), U8(1), //
5634 B(Star), R(1), //
5635 B(Jump), U8(8), //
5636 B(LdaSmi8), U8(2), //
5637 B(Star), R(1), //
5638 B(Jump), U8(2), //
5639 B(LdaUndefined), //
5640 B(Return), //
5641 }},
5642 {"var a = 1;\n"
5643 "switch(a) {\n"
5644 " case 1:\n" REPEAT_64(SPACE, " a = 2;")
5645 "break;\n"
5646 " case 2: a = 3; break;"
5647 "}\n",
5648 3 * kPointerSize,
5649 1,
5650 288,
5651 {
5652 B(LdaSmi8), U8(1), //
5653 B(Star), R(1), //
5654 B(Star), R(0), //
5655 B(Star), R(2), //
5656 B(LdaSmi8), U8(1), //
5657 B(TestEqualStrict), R(2), //
5658 B(JumpIfTrue), U8(10), //
5659 B(LdaSmi8), U8(2), //
5660 B(TestEqualStrict), R(2), //
5661 B(JumpIfTrueConstant), U8(0), //
5662 B(JumpConstant), U8(1), //
5663 REPEAT_64(COMMA, //
5664 B(LdaSmi8), U8(2), //
5665 B(Star), R(1)), //
5666 B(Jump), U8(8), //
5667 B(LdaSmi8), U8(3), //
5668 B(Star), R(1), //
5669 B(Jump), U8(2), //
5670 B(LdaUndefined), //
5671 B(Return), //
5672 },
5673 2,
5674 {262, 266}},
5675 {"var a = 1;\n"
5676 "switch(a) {\n"
5677 " case 1: \n"
5678 " switch(a + 1) {\n"
5679 " case 2 : a = 1; break;\n"
5680 " default : a = 2; break;\n"
5681 " } // fall-through\n"
5682 " case 2: a = 3;\n"
5683 "}\n",
5684 5 * kPointerSize,
5685 1,
5686 60,
5687 {
5688 B(LdaSmi8), U8(1), //
5689 B(Star), R(2), //
5690 B(Star), R(0), //
5691 B(Star), R(3), //
5692 B(LdaSmi8), U8(1), //
5693 B(TestEqualStrict), R(3), //
5694 B(JumpIfTrue), U8(10), //
5695 B(LdaSmi8), U8(2), //
5696 B(TestEqualStrict), R(3), //
5697 B(JumpIfTrue), U8(36), //
5698 B(Jump), U8(38), //
5699 B(Ldar), R(2), //
5700 B(Star), R(4), //
5701 B(LdaSmi8), U8(1), //
5702 B(Add), R(4), //
5703 B(Star), R(1), //
5704 B(Star), R(4), //
5705 B(LdaSmi8), U8(2), //
5706 B(TestEqualStrict), R(4), //
5707 B(JumpIfTrue), U8(4), //
5708 B(Jump), U8(8), //
5709 B(LdaSmi8), U8(1), //
5710 B(Star), R(2), //
5711 B(Jump), U8(8), //
5712 B(LdaSmi8), U8(2), //
5713 B(Star), R(2), //
5714 B(Jump), U8(2), //
5715 B(LdaSmi8), U8(3), //
5716 B(Star), R(2), //
5717 B(LdaUndefined), //
5718 B(Return), //
5719 }},
5720 };
5721
5722 for (size_t i = 0; i < arraysize(snippets); i++) {
5723 Handle<BytecodeArray> bytecode_array =
5724 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
5725 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
5726 }
5727}
5728
5729
5730TEST(BasicBlockToBoolean) {
5731 InitializedHandleScope handle_scope;
5732 BytecodeGeneratorHelper helper;
5733
5734 // Check that we generate JumpIfToBoolean if they are at the start of basic
5735 // blocks.
5736 ExpectedSnippet<int> snippets[] = {
5737 {"var a = 1; if (a || a < 0) { return 1; }",
5738 2 * kPointerSize,
5739 1,
5740 20,
5741 {
5742 B(LdaSmi8), U8(1), //
5743 B(Star), R(0), //
5744 B(JumpIfToBooleanTrue), U8(9), //
5745 B(Ldar), R(0), //
5746 B(Star), R(1), //
5747 B(LdaZero), //
5748 B(TestLessThan), R(1), //
5749 B(JumpIfToBooleanFalse), U8(5), //
5750 B(LdaSmi8), U8(1), //
5751 B(Return), //
5752 B(LdaUndefined), //
5753 B(Return), //
5754 }},
5755 {"var a = 1; if (a && a < 0) { return 1; }",
5756 2 * kPointerSize,
5757 1,
5758 20,
5759 {
5760 B(LdaSmi8), U8(1), //
5761 B(Star), R(0), //
5762 B(JumpIfToBooleanFalse), U8(9), //
5763 B(Ldar), R(0), //
5764 B(Star), R(1), //
5765 B(LdaZero), //
5766 B(TestLessThan), R(1), //
5767 B(JumpIfToBooleanFalse), U8(5), //
5768 B(LdaSmi8), U8(1), //
5769 B(Return), //
5770 B(LdaUndefined), //
5771 B(Return), //
5772 }},
5773 {"var a = 1; a = (a || a < 0) ? 2 : 3;",
5774 2 * kPointerSize,
5775 1,
5776 25,
5777 {
5778 B(LdaSmi8), U8(1), //
5779 B(Star), R(0), //
5780 B(JumpIfToBooleanTrue), U8(9), //
5781 B(Ldar), R(0), //
5782 B(Star), R(1), //
5783 B(LdaZero), //
5784 B(TestLessThan), R(1), //
5785 B(JumpIfToBooleanFalse), U8(6), //
5786 B(LdaSmi8), U8(2), //
5787 B(Jump), U8(4), //
5788 B(LdaSmi8), U8(3), //
5789 B(Star), R(0), //
5790 B(LdaUndefined), //
5791 B(Return), //
5792 }},
5793 };
5794
5795 for (size_t i = 0; i < arraysize(snippets); i++) {
5796 Handle<BytecodeArray> bytecode_array =
5797 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
5798 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
5799 }
5800}
5801
5802
5803TEST(DeadCodeRemoval) {
5804 InitializedHandleScope handle_scope;
5805 BytecodeGeneratorHelper helper;
5806
5807 ExpectedSnippet<int> snippets[] = {
5808 {"return; var a = 1; a();",
5809 1 * kPointerSize,
5810 1,
5811 2,
5812 {
5813 B(LdaUndefined), //
5814 B(Return), //
5815 }},
5816 {"if (false) { return; }; var a = 1;",
5817 1 * kPointerSize,
5818 1,
5819 6,
5820 {
5821 B(LdaSmi8), U8(1), //
5822 B(Star), R(0), //
5823 B(LdaUndefined), //
5824 B(Return), //
5825 }},
5826 {"if (true) { return 1; } else { return 2; };",
5827 0,
5828 1,
5829 3,
5830 {
5831 B(LdaSmi8), U8(1), //
5832 B(Return), //
5833 }},
5834 {"var a = 1; if (a) { return 1; }; return 2;",
5835 1 * kPointerSize,
5836 1,
5837 12,
5838 {
5839 B(LdaSmi8), U8(1), //
5840 B(Star), R(0), //
5841 B(JumpIfToBooleanFalse), U8(5), //
5842 B(LdaSmi8), U8(1), //
5843 B(Return), //
5844 B(LdaSmi8), U8(2), //
5845 B(Return), //
5846 }},
5847 };
5848
5849 for (size_t i = 0; i < arraysize(snippets); i++) {
5850 Handle<BytecodeArray> bytecode_array =
5851 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
5852 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
5853 }
5854}
5855
5856
5857TEST(ThisFunction) {
5858 InitializedHandleScope handle_scope;
5859 BytecodeGeneratorHelper helper;
5860
5861 int closure = Register::function_closure().index();
5862
5863 ExpectedSnippet<int> snippets[] = {
5864 {"var f;\n f = function f() { }",
5865 1 * kPointerSize,
5866 1,
5867 9,
5868 {
5869 B(LdaTheHole), //
5870 B(Star), R(0), //
5871 B(Ldar), R(closure), //
5872 B(Star), R(0), //
5873 B(LdaUndefined), //
5874 B(Return), //
5875 }},
5876 {"var f;\n f = function f() { return f; }",
5877 1 * kPointerSize,
5878 1,
5879 8,
5880 {
5881 B(LdaTheHole), //
5882 B(Star), R(0), //
5883 B(Ldar), R(closure), //
5884 B(Star), R(0), //
5885 B(Return), //
5886 }},
5887 };
5888
5889 for (size_t i = 0; i < arraysize(snippets); i++) {
5890 Handle<BytecodeArray> bytecode_array =
5891 helper.MakeBytecodeForFunction(snippets[i].code_snippet);
5892 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
5893 }
5894}
5895
5896
5897TEST(NewTarget) {
5898 InitializedHandleScope handle_scope;
5899 BytecodeGeneratorHelper helper;
5900
5901 int new_target = Register::new_target().index();
5902
5903 ExpectedSnippet<int> snippets[] = {
5904 {"return new.target;",
5905 1 * kPointerSize,
5906 1,
5907 5,
5908 {
5909 B(Ldar), R(new_target), //
5910 B(Star), R(0), //
5911 B(Return), //
5912 }},
5913 {"new.target;",
5914 1 * kPointerSize,
5915 1,
5916 6,
5917 {
5918 B(Ldar), R(new_target), //
5919 B(Star), R(0), //
5920 B(LdaUndefined), //
5921 B(Return), //
5922 }},
5923 };
5924
5925 for (size_t i = 0; i < arraysize(snippets); i++) {
5926 Handle<BytecodeArray> bytecode_array =
5927 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
5928 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
5929 }
5930}
5931
5932
5933TEST(RemoveRedundantLdar) {
5934 InitializedHandleScope handle_scope;
5935 BytecodeGeneratorHelper helper;
5936
5937 ExpectedSnippet<int> snippets[] = {
5938 {"var ld_a = 1;\n" // This test is to check Ldar does not
5939 "while(true) {\n" // get removed if the preceding Star is
5940 " ld_a = ld_a + ld_a;\n" // in a different basicblock.
5941 " if (ld_a > 10) break;\n"
5942 "}\n"
5943 "return ld_a;",
5944 2 * kPointerSize,
5945 1,
5946 29,
5947 {B(LdaSmi8), U8(1), //
5948 B(Star), R(0), //
5949 B(Ldar), R(0), // This load should not be removed as it
5950 B(Star), R(1), // is the target of the branch.
5951 B(Ldar), R(0), //
5952 B(Add), R(1), //
5953 B(Star), R(0), //
5954 B(Star), R(1), //
5955 B(LdaSmi8), U8(10), //
5956 B(TestGreaterThan), R(1), //
5957 B(JumpIfFalse), U8(4), //
5958 B(Jump), U8(4), //
5959 B(Jump), U8(-20), //
5960 B(Ldar), R(0), //
5961 B(Return)}},
5962 {"var ld_a = 1;\n"
5963 "do {\n"
5964 " ld_a = ld_a + ld_a;\n"
5965 " if (ld_a > 10) continue;\n"
5966 "} while(false);\n"
5967 "return ld_a;",
5968 2 * kPointerSize,
5969 1,
5970 27,
5971 {B(LdaSmi8), U8(1), //
5972 B(Star), R(0), //
5973 B(Ldar), R(0), //
5974 B(Star), R(1), //
5975 B(Ldar), R(0), //
5976 B(Add), R(1), //
5977 B(Star), R(0), //
5978 B(Star), R(1), //
5979 B(LdaSmi8), U8(10), //
5980 B(TestGreaterThan), R(1), //
5981 B(JumpIfFalse), U8(4), //
5982 B(Jump), U8(2), //
5983 B(Ldar), R(0), //
5984 B(Return)}},
5985 {"var ld_a = 1;\n"
5986 " ld_a = ld_a + ld_a;\n"
5987 " return ld_a;",
5988 2 * kPointerSize,
5989 1,
5990 13,
5991 {
5992 B(LdaSmi8), U8(1), //
5993 B(Star), R(0), //
5994 B(Star), R(1), //
5995 B(Ldar), R(0), //
5996 B(Add), R(1), //
5997 B(Star), R(0), //
5998 B(Return) //
5999 }},
6000 };
6001
6002 for (size_t i = 0; i < arraysize(snippets); i++) {
6003 Handle<BytecodeArray> bytecode_array =
6004 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
6005 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
6006 }
6007}
6008
6009
6010TEST(AssignmentsInBinaryExpression) {
6011 InitializedHandleScope handle_scope;
6012 BytecodeGeneratorHelper helper;
6013
6014 ExpectedSnippet<const char*> snippets[] = {
6015 {"var x = 0, y = 1;\n"
6016 "return (x = 2, y = 3, x = 4, y = 5)",
6017 2 * kPointerSize,
6018 1,
6019 24,
6020 {
6021 B(LdaZero), B(Star), R(0), //
6022 B(LdaSmi8), U8(1), //
6023 B(Star), R(1), //
6024 B(LdaSmi8), U8(2), //
6025 B(Star), R(0), //
6026 B(LdaSmi8), U8(3), //
6027 B(Star), R(1), //
6028 B(LdaSmi8), U8(4), //
6029 B(Star), R(0), //
6030 B(LdaSmi8), U8(5), //
6031 B(Star), R(1), //
6032 B(Return), //
6033 },
6034 0},
6035 {"var x = 55;\n"
6036 "var y = (x = 100);\n"
6037 "return y",
6038 2 * kPointerSize,
6039 1,
6040 11,
6041 {
6042 B(LdaSmi8), U8(55), //
6043 B(Star), R(0), //
6044 B(LdaSmi8), U8(100), //
6045 B(Star), R(0), //
6046 B(Star), R(1), //
6047 B(Return), //
6048 },
6049 0},
6050 {"var x = 55;\n"
6051 "x = x + (x = 100) + (x = 101);\n"
6052 "return x;",
6053 3 * kPointerSize,
6054 1,
6055 23,
6056 {
6057 B(LdaSmi8), U8(55), //
6058 B(Star), R(0), //
6059 B(Star), R(1), //
6060 B(LdaSmi8), U8(100), //
6061 B(Star), R(0), //
6062 B(Add), R(1), //
6063 B(Star), R(2), //
6064 B(LdaSmi8), U8(101), //
6065 B(Star), R(0), //
6066 B(Add), R(2), //
6067 B(Star), R(0), //
6068 B(Return), //
6069 },
6070 0},
6071 {"var x = 55;\n"
6072 "x = (x = 56) - x + (x = 57);\n"
6073 "x++;\n"
6074 "return x;",
6075 3 * kPointerSize,
6076 1,
6077 31,
6078 {
6079 B(LdaSmi8), U8(55), //
6080 B(Star), R(0), //
6081 B(LdaSmi8), U8(56), //
6082 B(Star), R(0), //
6083 B(Star), R(1), //
6084 B(Ldar), R(0), //
6085 B(Sub), R(1), //
6086 B(Star), R(2), //
6087 B(LdaSmi8), U8(57), //
6088 B(Star), R(0), //
6089 B(Add), R(2), //
6090 B(Star), R(0), //
6091 B(ToNumber), //
6092 B(Star), R(1), //
6093 B(Inc), //
6094 B(Star), R(0), //
6095 B(Return), //
6096 },
6097 0},
6098 {"var x = 55;\n"
6099 "var y = x + (x = 1) + (x = 2) + (x = 3);\n"
6100 "return y;",
6101 4 * kPointerSize,
6102 1,
6103 31,
6104 {
6105 B(LdaSmi8), U8(55), //
6106 B(Star), R(0), //
6107 B(Star), R(2), //
6108 B(LdaSmi8), U8(1), //
6109 B(Star), R(0), //
6110 B(Add), R(2), //
6111 B(Star), R(3), //
6112 B(LdaSmi8), U8(2), //
6113 B(Star), R(0), //
6114 B(Add), R(3), //
6115 B(Star), R(2), //
6116 B(LdaSmi8), U8(3), //
6117 B(Star), R(0), //
6118 B(Add), R(2), //
6119 B(Star), R(1), //
6120 B(Return), //
6121 },
6122 0},
6123 {"var x = 55;\n"
6124 "var x = x + (x = 1) + (x = 2) + (x = 3);\n"
6125 "return x;",
6126 3 * kPointerSize,
6127 1,
6128 31,
6129 {
6130 B(LdaSmi8), U8(55), //
6131 B(Star), R(0), //
6132 B(Star), R(1), //
6133 B(LdaSmi8), U8(1), //
6134 B(Star), R(0), //
6135 B(Add), R(1), //
6136 B(Star), R(2), //
6137 B(LdaSmi8), U8(2), //
6138 B(Star), R(0), //
6139 B(Add), R(2), //
6140 B(Star), R(1), //
6141 B(LdaSmi8), U8(3), //
6142 B(Star), R(0), //
6143 B(Add), R(1), //
6144 B(Star), R(0), //
6145 B(Return), //
6146 },
6147 0},
6148 {"var x = 10, y = 20;\n"
6149 "return x + (x = 1) + (x + 1) * (y = 2) + (y = 3) + (x = 4) + (y = 5) + "
6150 "y;\n",
6151 5 * kPointerSize,
6152 1,
6153 69,
6154 {
6155 B(LdaSmi8), U8(10), //
6156 B(Star), R(0), //
6157 B(LdaSmi8), U8(20), //
6158 B(Star), R(1), //
6159 B(Ldar), R(0), //
6160 B(Star), R(2), //
6161 B(LdaSmi8), U8(1), //
6162 B(Star), R(0), //
6163 B(Add), R(2), //
6164 B(Star), R(3), //
6165 B(Ldar), R(0), //
6166 B(Star), R(2), //
6167 B(LdaSmi8), U8(1), //
6168 B(Add), R(2), //
6169 B(Star), R(4), //
6170 B(LdaSmi8), U8(2), //
6171 B(Star), R(1), //
6172 B(Mul), R(4), //
6173 B(Add), R(3), //
6174 B(Star), R(2), //
6175 B(LdaSmi8), U8(3), //
6176 B(Star), R(1), //
6177 B(Add), R(2), //
6178 B(Star), R(3), //
6179 B(LdaSmi8), U8(4), //
6180 B(Star), R(0), //
6181 B(Add), R(3), //
6182 B(Star), R(2), //
6183 B(LdaSmi8), U8(5), //
6184 B(Star), R(1), //
6185 B(Add), R(2), //
6186 B(Star), R(3), //
6187 B(Ldar), R(1), //
6188 B(Add), R(3), //
6189 B(Return), //
6190 },
6191 0},
6192 {"var x = 17;\n"
6193 "return 1 + x + (x++) + (++x);\n",
6194 4 * kPointerSize,
6195 1,
6196 37,
6197 {
6198 B(LdaSmi8), U8(17), //
6199 B(Star), R(0), //
6200 B(LdaSmi8), U8(1), //
6201 B(Star), R(1), //
6202 B(Ldar), R(0), //
6203 B(Add), R(1), //
6204 B(Star), R(2), //
6205 B(Ldar), R(0), //
6206 B(ToNumber), //
6207 B(Star), R(1), //
6208 B(Inc), //
6209 B(Star), R(0), //
6210 B(Ldar), R(1), //
6211 B(Add), R(2), //
6212 B(Star), R(3), //
6213 B(Ldar), R(0), //
6214 B(ToNumber), //
6215 B(Inc), //
6216 B(Star), R(0), //
6217 B(Add), R(3), //
6218 B(Return), //
6219 },
6220 0}};
6221
6222 for (size_t i = 0; i < arraysize(snippets); i++) {
6223 Handle<BytecodeArray> bytecode_array =
6224 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
6225 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
6226 }
6227}
6228
6229
6230TEST(Eval) {
6231 InitializedHandleScope handle_scope;
6232 BytecodeGeneratorHelper helper;
6233 Zone zone;
6234
6235 int closure = Register::function_closure().index();
6236 int context = Register::function_context().index();
6237 int new_target = Register::new_target().index();
6238
6239 int first_context_slot = Context::MIN_CONTEXT_SLOTS;
6240
6241 ExpectedSnippet<const char*> snippets[] = {
6242 {"return eval('1;');",
6243 9 * kPointerSize,
6244 1,
6245 67,
6246 {
6247 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
6248 U8(1), //
6249 B(PushContext), R(0), //
6250 B(Ldar), THIS(1), //
6251 B(StaContextSlot), R(0), U8(first_context_slot), //
6252 B(CreateMappedArguments), //
6253 B(StaContextSlot), R(0), U8(first_context_slot + 1), //
6254 B(Ldar), R(new_target), //
6255 B(StaContextSlot), R(0), U8(first_context_slot + 2), //
6256 B(Mov), R(context), R(3), //
6257 B(LdaConstant), U8(0), //
6258 B(Star), R(4), //
6259 B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), //
6260 R(3), U8(2), R(1), //
6261 B(LdaConstant), U8(1), //
6262 B(Star), R(3), //
6263 B(Mov), R(1), R(4), //
6264 B(Mov), R(3), R(5), //
6265 B(Mov), R(closure), R(6), //
6266 B(LdaZero), //
6267 B(Star), R(7), //
6268 B(LdaSmi8), U8(10), //
6269 B(Star), R(8), //
6270 B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
6271 U8(5), //
6272 B(Star), R(1), //
6273 B(Call), R(1), R(2), U8(1), U8(0), //
6274 B(Return), //
6275 },
6276 2,
6277 {"eval", "1;"}},
6278 };
6279
6280 for (size_t i = 0; i < arraysize(snippets); i++) {
6281 Handle<BytecodeArray> bytecode_array =
6282 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
6283 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
6284 }
6285}
6286
6287
6288TEST(LookupSlot) {
6289 InitializedHandleScope handle_scope;
6290 BytecodeGeneratorHelper helper;
6291
6292 int closure = Register::function_closure().index();
6293 int first_context_slot = Context::MIN_CONTEXT_SLOTS;
6294 int context = Register::function_context().index();
6295 int new_target = Register::new_target().index();
6296
6297 ExpectedSnippet<const char*> snippets[] = {
6298 {"eval('var x = 10;'); return x;",
6299 9 * kPointerSize,
6300 1,
6301 69,
6302 {
6303 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
6304 U8(1), //
6305 B(PushContext), R(0), //
6306 B(Ldar), THIS(1), //
6307 B(StaContextSlot), R(0), U8(first_context_slot), //
6308 B(CreateMappedArguments), //
6309 B(StaContextSlot), R(0), U8(first_context_slot + 1), //
6310 B(Ldar), R(new_target), //
6311 B(StaContextSlot), R(0), U8(first_context_slot + 2), //
6312 B(Mov), R(context), R(3), //
6313 B(LdaConstant), U8(0), //
6314 B(Star), R(4), //
6315 B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), //
6316 R(3), U8(2), R(1), //
6317 B(LdaConstant), U8(1), //
6318 B(Star), R(3), //
6319 B(Mov), R(1), R(4), //
6320 B(Mov), R(3), R(5), //
6321 B(Mov), R(closure), R(6), //
6322 B(LdaZero), //
6323 B(Star), R(7), //
6324 B(LdaSmi8), U8(10), //
6325 B(Star), R(8), //
6326 B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
6327 U8(5), //
6328 B(Star), R(1), //
6329 B(Call), R(1), R(2), U8(1), U8(0), //
6330 B(LdaLookupSlot), U8(2), //
6331 B(Return), //
6332 },
6333 3,
6334 {"eval", "var x = 10;", "x"}},
6335 {"eval('var x = 10;'); return typeof x;",
6336 9 * kPointerSize,
6337 1,
6338 70,
6339 {
6340 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
6341 U8(1), //
6342 B(PushContext), R(0), //
6343 B(Ldar), THIS(1), //
6344 B(StaContextSlot), R(0), U8(first_context_slot), //
6345 B(CreateMappedArguments), //
6346 B(StaContextSlot), R(0), U8(first_context_slot + 1), //
6347 B(Ldar), R(new_target), //
6348 B(StaContextSlot), R(0), U8(first_context_slot + 2), //
6349 B(Mov), R(context), R(3), //
6350 B(LdaConstant), U8(0), //
6351 B(Star), R(4), //
6352 B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), //
6353 R(3), U8(2), R(1), //
6354 B(LdaConstant), U8(1), //
6355 B(Star), R(3), //
6356 B(Mov), R(1), R(4), //
6357 B(Mov), R(3), R(5), //
6358 B(Mov), R(closure), R(6), //
6359 B(LdaZero), //
6360 B(Star), R(7), //
6361 B(LdaSmi8), U8(10), //
6362 B(Star), R(8), //
6363 B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
6364 U8(5), //
6365 B(Star), R(1), //
6366 B(Call), R(1), R(2), U8(1), U8(0), //
6367 B(LdaLookupSlotInsideTypeof), U8(2), //
6368 B(TypeOf), //
6369 B(Return), //
6370 },
6371 3,
6372 {"eval", "var x = 10;", "x"}},
6373 {"x = 20; return eval('');",
6374 9 * kPointerSize,
6375 1,
6376 71,
6377 {
6378 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
6379 U8(1), //
6380 B(PushContext), R(0), //
6381 B(Ldar), THIS(1), //
6382 B(StaContextSlot), R(0), U8(first_context_slot), //
6383 B(CreateMappedArguments), //
6384 B(StaContextSlot), R(0), U8(first_context_slot + 1), //
6385 B(Ldar), R(new_target), //
6386 B(StaContextSlot), R(0), U8(first_context_slot + 2), //
6387 B(LdaSmi8), U8(20), //
6388 B(StaLookupSlotSloppy), U8(0), //
6389 B(Mov), R(context), R(3), //
6390 B(LdaConstant), U8(1), //
6391 B(Star), R(4), //
6392 B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), //
6393 R(3), U8(2), R(1), //
6394 B(LdaConstant), U8(2), //
6395 B(Star), R(3), //
6396 B(Mov), R(1), R(4), //
6397 B(Mov), R(3), R(5), //
6398 B(Mov), R(closure), R(6), //
6399 B(LdaZero), //
6400 B(Star), R(7), //
6401 B(LdaSmi8), U8(10), //
6402 B(Star), R(8), //
6403 B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
6404 U8(5), //
6405 B(Star), R(1), //
6406 B(Call), R(1), R(2), U8(1), U8(0), //
6407 B(Return), //
6408 },
6409 3,
6410 {"x", "eval", ""}},
6411 };
6412
6413 for (size_t i = 0; i < arraysize(snippets); i++) {
6414 Handle<BytecodeArray> bytecode_array =
6415 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
6416 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
6417 }
6418}
6419
6420
6421TEST(CallLookupSlot) {
6422 InitializedHandleScope handle_scope;
6423 BytecodeGeneratorHelper helper;
6424 Zone zone;
6425
6426 FeedbackVectorSpec feedback_spec(&zone);
6427 FeedbackVectorSlot slot1 = feedback_spec.AddLoadICSlot();
6428 FeedbackVectorSlot slot2 = feedback_spec.AddCallICSlot();
6429 USE(slot1);
6430
6431 Handle<i::TypeFeedbackVector> vector =
6432 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
6433
6434 int closure = Register::function_closure().index();
6435 int context = Register::function_context().index();
6436 int new_target = Register::new_target().index();
6437
6438 ExpectedSnippet<InstanceType> snippets[] = {
6439 {"g = function(){}; eval(''); return g();",
6440 9 * kPointerSize,
6441 1,
6442 90,
6443 {
6444 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
6445 U8(1), //
6446 B(PushContext), R(0), //
6447 B(Ldar), THIS(1), //
6448 B(StaContextSlot), R(0), U8(4), //
6449 B(CreateMappedArguments), //
6450 B(StaContextSlot), R(0), U8(5), //
6451 B(Ldar), R(new_target), //
6452 B(StaContextSlot), R(0), U8(6), //
6453 B(CreateClosure), U8(0), U8(0), //
6454 B(StaLookupSlotSloppy), U8(1), //
6455 B(Mov), R(context), R(3), //
6456 B(LdaConstant), U8(2), //
6457 B(Star), R(4), //
6458 B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), //
6459 R(3), U8(2), R(1), //
6460 B(LdaConstant), U8(3), //
6461 B(Star), R(3), //
6462 B(Mov), R(1), R(4), //
6463 B(Mov), R(3), R(5), //
6464 B(Mov), R(closure), R(6), //
6465 B(LdaZero), //
6466 B(Star), R(7), //
6467 B(LdaSmi8), U8(10), //
6468 B(Star), R(8), //
6469 B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
6470 U8(5), //
6471 B(Star), R(1), //
6472 B(Call), R(1), R(2), U8(1), U8(0), //
6473 B(Mov), R(context), R(3), //
6474 B(LdaConstant), U8(1), //
6475 B(Star), R(4), //
6476 B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), //
6477 R(3), U8(2), R(1), //
6478 B(Call), R(1), R(2), U8(0), U8(vector->GetIndex(slot2)), //
6479 B(Return), //
6480 },
6481 4,
6482 {InstanceType::SHARED_FUNCTION_INFO_TYPE,
6483 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
6484 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
6485 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
6486 };
6487
6488 for (size_t i = 0; i < arraysize(snippets); i++) {
6489 Handle<BytecodeArray> bytecode_array =
6490 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
6491 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
6492 }
6493}
6494
6495
6496TEST(LookupSlotInEval) {
6497 InitializedHandleScope handle_scope;
6498 BytecodeGeneratorHelper helper;
6499
6500 const char* function_prologue = "var f;"
6501 "var x = 1;"
6502 "function f1() {"
6503 " eval(\"function t() {";
6504 const char* function_epilogue = " }; f = t; f();\");"
6505 "}"
6506 "f1();";
6507
6508 ExpectedSnippet<const char*> snippets[] = {
6509 {"return x;",
6510 0 * kPointerSize,
6511 1,
6512 3,
6513 {
6514 B(LdaLookupSlot), U8(0), //
6515 B(Return) //
6516 },
6517 1,
6518 {"x"}},
6519 {"x = 10;",
6520 0 * kPointerSize,
6521 1,
6522 6,
6523 {
6524 B(LdaSmi8), U8(10), //
6525 B(StaLookupSlotSloppy), U8(0), //
6526 B(LdaUndefined), //
6527 B(Return), //
6528 },
6529 1,
6530 {"x"}},
6531 {"'use strict'; x = 10;",
6532 0 * kPointerSize,
6533 1,
6534 6,
6535 {
6536 B(LdaSmi8), U8(10), //
6537 B(StaLookupSlotStrict), U8(0), //
6538 B(LdaUndefined), //
6539 B(Return), //
6540 },
6541 1,
6542 {"x"}},
6543 {"return typeof x;",
6544 0 * kPointerSize,
6545 1,
6546 4,
6547 {
6548 B(LdaLookupSlotInsideTypeof), U8(0), //
6549 B(TypeOf), //
6550 B(Return), //
6551 },
6552 1,
6553 {"x"}},
6554 };
6555
6556 for (size_t i = 0; i < arraysize(snippets); i++) {
6557 std::string script = std::string(function_prologue) +
6558 std::string(snippets[i].code_snippet) +
6559 std::string(function_epilogue);
6560 // TODO(mythria): use * as filter when function declarations are supported
6561 // inside eval.
6562 Handle<BytecodeArray> bytecode_array =
6563 helper.MakeBytecode(script.c_str(), "t", "f");
6564 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
6565 }
6566}
6567
6568
6569TEST(LookupSlotWideInEval) {
6570 InitializedHandleScope handle_scope;
6571 BytecodeGeneratorHelper helper;
6572
6573 const char* function_prologue =
6574 "var f;"
6575 "var x = 1;"
6576 "function f1() {"
6577 " eval(\"function t() {";
6578 const char* function_epilogue =
6579 " }; f = t; f();\");"
6580 "}"
6581 "f1();";
6582
6583 int const_count[] = {0, 0, 0, 0};
6584 ExpectedSnippet<InstanceType, 257> snippets[] = {
6585 {REPEAT_256(SPACE, "var y = 2.3;")
6586 "return x;",
6587 1 * kPointerSize,
6588 1,
6589 1028,
6590 {
6591 REPEAT_256(SPACE, //
6592 B(LdaConstant), U8(const_count[0]++), //
6593 B(Star), R(0), ) //
6594 B(LdaLookupSlotWide), U16(256), //
6595 B(Return) //
6596 },
6597 257,
6598 {REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE),
6599 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
6600 {REPEAT_256(SPACE, "var y = 2.3;")
6601 "return typeof x;",
6602 1 * kPointerSize,
6603 1,
6604 1029,
6605 {
6606 REPEAT_256(SPACE, //
6607 B(LdaConstant), U8(const_count[1]++), //
6608 B(Star), R(0), ) //
6609 B(LdaLookupSlotInsideTypeofWide), U16(256), //
6610 B(TypeOf), //
6611 B(Return) //
6612 },
6613 257,
6614 {REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE),
6615 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
6616 {REPEAT_256(SPACE, "var y = 2.3;")
6617 "x = 10;",
6618 1 * kPointerSize,
6619 1,
6620 1031,
6621 {
6622 REPEAT_256(SPACE, //
6623 B(LdaConstant), U8(const_count[2]++), //
6624 B(Star), R(0), ) //
6625 B(LdaSmi8), U8(10), //
6626 B(StaLookupSlotSloppyWide), U16(256), //
6627 B(LdaUndefined), //
6628 B(Return) //
6629 },
6630 257,
6631 {REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE),
6632 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
6633 {"'use strict';"
6634 REPEAT_256(SPACE, "var y = 2.3;")
6635 "x = 10;",
6636 1 * kPointerSize,
6637 1,
6638 1031,
6639 {
6640 REPEAT_256(SPACE,
6641 B(LdaConstant), U8(const_count[3]++), //
6642 B(Star), R(0), ) //
6643 B(LdaSmi8), U8(10), //
6644 B(StaLookupSlotStrictWide), U16(256), //
6645 B(LdaUndefined), //
6646 B(Return) //
6647 },
6648 257,
6649 {REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE),
6650 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
6651 };
6652
6653 for (size_t i = 0; i < arraysize(snippets); i++) {
6654 std::string script = std::string(function_prologue) +
6655 std::string(snippets[i].code_snippet) +
6656 std::string(function_epilogue);
6657 // TODO(mythria): use * as filter when function declarations are supported
6658 // inside eval.
6659 Handle<BytecodeArray> bytecode_array =
6660 helper.MakeBytecode(script.c_str(), "t", "f");
6661 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
6662 }
6663}
6664
6665
6666TEST(DeleteLookupSlotInEval) {
6667 InitializedHandleScope handle_scope;
6668 BytecodeGeneratorHelper helper;
6669
6670 const char* function_prologue = "var f;"
6671 "var x = 1;"
6672 "z = 10;"
6673 "function f1() {"
6674 " var y;"
6675 " eval(\"function t() {";
6676 const char* function_epilogue = " }; f = t; f();\");"
6677 "}"
6678 "f1();";
6679
6680 ExpectedSnippet<const char*> snippets[] = {
6681 {"delete x;",
6682 0 * kPointerSize,
6683 1,
6684 5,
6685 {
6686 B(LdaConstant), U8(0), //
6687 B(DeleteLookupSlot), //
6688 B(LdaUndefined), //
6689 B(Return) //
6690 },
6691 1,
6692 {"x"}},
6693 {"return delete y;",
6694 0 * kPointerSize,
6695 1,
6696 2,
6697 {
6698 B(LdaFalse), //
6699 B(Return) //
6700 },
6701 0},
6702 {"return delete z;",
6703 0 * kPointerSize,
6704 1,
6705 4,
6706 {
6707 B(LdaConstant), U8(0), //
6708 B(DeleteLookupSlot), //
6709 B(Return) //
6710 },
6711 1,
6712 {"z"}},
6713 };
6714
6715 for (size_t i = 0; i < arraysize(snippets); i++) {
6716 std::string script = std::string(function_prologue) +
6717 std::string(snippets[i].code_snippet) +
6718 std::string(function_epilogue);
6719 Handle<BytecodeArray> bytecode_array =
6720 helper.MakeBytecode(script.c_str(), "t", "f");
6721 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
6722 }
6723}
6724
6725} // namespace interpreter
6726} // namespace internal
6727} // namespace v8