OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/interpreter/bytecode-array-builder.h" | 7 #include "src/interpreter/bytecode-array-builder.h" |
8 #include "src/interpreter/bytecode-array-iterator.h" | 8 #include "src/interpreter/bytecode-array-iterator.h" |
9 #include "src/interpreter/bytecode-label.h" | 9 #include "src/interpreter/bytecode-label.h" |
10 #include "src/interpreter/bytecode-register-allocator.h" | 10 #include "src/interpreter/bytecode-register-allocator.h" |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 .CompareOperation(Token::Value::IN, reg); | 164 .CompareOperation(Token::Value::IN, reg); |
165 | 165 |
166 // Emit cast operator invocations. | 166 // Emit cast operator invocations. |
167 builder.CastAccumulatorToNumber() | 167 builder.CastAccumulatorToNumber() |
168 .CastAccumulatorToJSObject() | 168 .CastAccumulatorToJSObject() |
169 .CastAccumulatorToName(); | 169 .CastAccumulatorToName(); |
170 | 170 |
171 // Emit control flow. Return must be the last instruction. | 171 // Emit control flow. Return must be the last instruction. |
172 BytecodeLabel start; | 172 BytecodeLabel start; |
173 builder.Bind(&start); | 173 builder.Bind(&start); |
174 // Short jumps with Imm8 operands | 174 { |
175 builder.Jump(&start) | 175 // Short jumps with Imm8 operands |
176 .JumpIfNull(&start) | 176 BytecodeLabel after_jump; |
177 .JumpIfUndefined(&start) | 177 builder.Jump(&start) |
178 .JumpIfNotHole(&start); | 178 .Bind(&after_jump) |
| 179 .JumpIfNull(&start) |
| 180 .JumpIfUndefined(&start) |
| 181 .JumpIfNotHole(&start); |
| 182 } |
179 | 183 |
180 // Longer jumps with constant operands | 184 // Longer jumps with constant operands |
181 BytecodeLabel end[8]; | 185 BytecodeLabel end[8]; |
182 builder.Jump(&end[0]) | 186 { |
183 .LoadTrue() | 187 BytecodeLabel after_jump; |
184 .JumpIfTrue(&end[1]) | 188 builder.Jump(&end[0]) |
185 .LoadTrue() | 189 .Bind(&after_jump) |
186 .JumpIfFalse(&end[2]) | 190 .LoadTrue() |
187 .LoadLiteral(Smi::FromInt(0)) | 191 .JumpIfTrue(&end[1]) |
188 .JumpIfTrue(&end[3]) | 192 .LoadTrue() |
189 .LoadLiteral(Smi::FromInt(0)) | 193 .JumpIfFalse(&end[2]) |
190 .JumpIfFalse(&end[4]) | 194 .LoadLiteral(Smi::FromInt(0)) |
191 .JumpIfNull(&end[5]) | 195 .JumpIfTrue(&end[3]) |
192 .JumpIfUndefined(&end[6]) | 196 .LoadLiteral(Smi::FromInt(0)) |
193 .JumpIfNotHole(&end[7]); | 197 .JumpIfFalse(&end[4]) |
| 198 .JumpIfNull(&end[5]) |
| 199 .JumpIfUndefined(&end[6]) |
| 200 .JumpIfNotHole(&end[7]); |
| 201 } |
194 | 202 |
195 // Perform an operation that returns boolean value to | 203 // Perform an operation that returns boolean value to |
196 // generate JumpIfTrue/False | 204 // generate JumpIfTrue/False |
197 builder.CompareOperation(Token::Value::EQ, reg) | 205 builder.CompareOperation(Token::Value::EQ, reg) |
198 .JumpIfTrue(&start) | 206 .JumpIfTrue(&start) |
199 .CompareOperation(Token::Value::EQ, reg) | 207 .CompareOperation(Token::Value::EQ, reg) |
200 .JumpIfFalse(&start); | 208 .JumpIfFalse(&start); |
201 // Perform an operation that returns a non-boolean operation to | 209 // Perform an operation that returns a non-boolean operation to |
202 // generate JumpIfToBooleanTrue/False. | 210 // generate JumpIfToBooleanTrue/False. |
203 builder.BinaryOperation(Token::Value::ADD, reg) | 211 builder.BinaryOperation(Token::Value::ADD, reg) |
204 .JumpIfTrue(&start) | 212 .JumpIfTrue(&start) |
205 .BinaryOperation(Token::Value::ADD, reg) | 213 .BinaryOperation(Token::Value::ADD, reg) |
206 .JumpIfFalse(&start); | 214 .JumpIfFalse(&start); |
207 // Insert dummy ops to force longer jumps | 215 // Insert dummy ops to force longer jumps |
208 for (int i = 0; i < 128; i++) { | 216 for (int i = 0; i < 128; i++) { |
209 builder.LoadTrue(); | 217 builder.LoadTrue(); |
210 } | 218 } |
211 // Longer jumps requiring Constant operand | 219 // Longer jumps requiring Constant operand |
212 builder.Jump(&start).JumpIfNull(&start).JumpIfUndefined(&start).JumpIfNotHole( | 220 { |
213 &start); | 221 BytecodeLabel after_jump; |
214 // Perform an operation that returns boolean value to | 222 builder.Jump(&start) |
215 // generate JumpIfTrue/False | 223 .Bind(&after_jump) |
216 builder.CompareOperation(Token::Value::EQ, reg) | 224 .JumpIfNull(&start) |
217 .JumpIfTrue(&start) | 225 .JumpIfUndefined(&start) |
218 .CompareOperation(Token::Value::EQ, reg) | 226 .JumpIfNotHole(&start); |
219 .JumpIfFalse(&start); | 227 // Perform an operation that returns boolean value to |
220 // Perform an operation that returns a non-boolean operation to | 228 // generate JumpIfTrue/False |
221 // generate JumpIfToBooleanTrue/False. | 229 builder.CompareOperation(Token::Value::EQ, reg) |
222 builder.BinaryOperation(Token::Value::ADD, reg) | 230 .JumpIfTrue(&start) |
223 .JumpIfTrue(&start) | 231 .CompareOperation(Token::Value::EQ, reg) |
224 .BinaryOperation(Token::Value::ADD, reg) | 232 .JumpIfFalse(&start); |
225 .JumpIfFalse(&start); | 233 // Perform an operation that returns a non-boolean operation to |
| 234 // generate JumpIfToBooleanTrue/False. |
| 235 builder.BinaryOperation(Token::Value::ADD, reg) |
| 236 .JumpIfTrue(&start) |
| 237 .BinaryOperation(Token::Value::ADD, reg) |
| 238 .JumpIfFalse(&start); |
| 239 } |
226 | 240 |
227 // Emit stack check bytecode. | 241 // Emit stack check bytecode. |
228 builder.StackCheck(0); | 242 builder.StackCheck(0); |
229 | 243 |
230 // Emit throw and re-throw in it's own basic block so that the rest of the | 244 // Emit throw and re-throw in it's own basic block so that the rest of the |
231 // code isn't omitted due to being dead. | 245 // code isn't omitted due to being dead. |
232 BytecodeLabel after_throw; | 246 BytecodeLabel after_throw; |
233 builder.Jump(&after_throw).Throw().Bind(&after_throw); | 247 builder.Throw().Bind(&after_throw); |
234 BytecodeLabel after_rethrow; | 248 BytecodeLabel after_rethrow; |
235 builder.Jump(&after_rethrow).ReThrow().Bind(&after_rethrow); | 249 builder.ReThrow().Bind(&after_rethrow); |
236 | 250 |
237 builder.ForInPrepare(reg) | 251 builder.ForInPrepare(reg) |
238 .ForInDone(reg, reg) | 252 .ForInDone(reg, reg) |
239 .ForInNext(reg, reg, reg, 1) | 253 .ForInNext(reg, reg, reg, 1) |
240 .ForInStep(reg); | 254 .ForInStep(reg); |
241 builder.ForInPrepare(wide) | 255 builder.ForInPrepare(wide) |
242 .ForInDone(reg, other) | 256 .ForInDone(reg, other) |
243 .ForInNext(wide, wide, wide, 1024) | 257 .ForInNext(wide, wide, wide, 1024) |
244 .ForInStep(reg); | 258 .ForInStep(reg); |
245 | 259 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
297 false); | 311 false); |
298 builder.CreateClosure(shared_info2, NOT_TENURED); | 312 builder.CreateClosure(shared_info2, NOT_TENURED); |
299 | 313 |
300 // Emit wide variant of literal creation operations. | 314 // Emit wide variant of literal creation operations. |
301 builder.CreateRegExpLiteral(factory->NewStringFromStaticChars("wide_literal"), | 315 builder.CreateRegExpLiteral(factory->NewStringFromStaticChars("wide_literal"), |
302 0, 0) | 316 0, 0) |
303 .CreateArrayLiteral(factory->NewFixedArray(2), 0, 0) | 317 .CreateArrayLiteral(factory->NewFixedArray(2), 0, 0) |
304 .CreateObjectLiteral(factory->NewFixedArray(2), 0, 0); | 318 .CreateObjectLiteral(factory->NewFixedArray(2), 0, 0); |
305 | 319 |
306 // Longer jumps requiring ConstantWide operand | 320 // Longer jumps requiring ConstantWide operand |
307 builder.Jump(&start).JumpIfNull(&start).JumpIfUndefined(&start).JumpIfNotHole( | 321 { |
308 &start); | 322 BytecodeLabel after_jump; |
| 323 builder.Jump(&start) |
| 324 .Bind(&after_jump) |
| 325 .JumpIfNull(&start) |
| 326 .JumpIfUndefined(&start) |
| 327 .JumpIfNotHole(&start); |
| 328 } |
309 | 329 |
310 // Perform an operation that returns boolean value to | 330 // Perform an operation that returns boolean value to |
311 // generate JumpIfTrue/False | 331 // generate JumpIfTrue/False |
312 builder.CompareOperation(Token::Value::EQ, reg) | 332 builder.CompareOperation(Token::Value::EQ, reg) |
313 .JumpIfTrue(&start) | 333 .JumpIfTrue(&start) |
314 .CompareOperation(Token::Value::EQ, reg) | 334 .CompareOperation(Token::Value::EQ, reg) |
315 .JumpIfFalse(&start); | 335 .JumpIfFalse(&start); |
316 | 336 |
317 // Perform an operation that returns a non-boolean operation to | 337 // Perform an operation that returns a non-boolean operation to |
318 // generate JumpIfToBooleanTrue/False. | 338 // generate JumpIfToBooleanTrue/False. |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 } | 519 } |
500 | 520 |
501 TEST_F(BytecodeArrayBuilderTest, ForwardJumps) { | 521 TEST_F(BytecodeArrayBuilderTest, ForwardJumps) { |
502 static const int kFarJumpDistance = 256; | 522 static const int kFarJumpDistance = 256; |
503 | 523 |
504 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1); | 524 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1); |
505 | 525 |
506 Register reg(0); | 526 Register reg(0); |
507 BytecodeLabel far0, far1, far2, far3, far4; | 527 BytecodeLabel far0, far1, far2, far3, far4; |
508 BytecodeLabel near0, near1, near2, near3, near4; | 528 BytecodeLabel near0, near1, near2, near3, near4; |
| 529 BytecodeLabel after_jump0, after_jump1; |
509 | 530 |
510 builder.Jump(&near0) | 531 builder.Jump(&near0) |
| 532 .Bind(&after_jump0) |
511 .CompareOperation(Token::Value::EQ, reg) | 533 .CompareOperation(Token::Value::EQ, reg) |
512 .JumpIfTrue(&near1) | 534 .JumpIfTrue(&near1) |
513 .CompareOperation(Token::Value::EQ, reg) | 535 .CompareOperation(Token::Value::EQ, reg) |
514 .JumpIfFalse(&near2) | 536 .JumpIfFalse(&near2) |
515 .BinaryOperation(Token::Value::ADD, reg) | 537 .BinaryOperation(Token::Value::ADD, reg) |
516 .JumpIfTrue(&near3) | 538 .JumpIfTrue(&near3) |
517 .BinaryOperation(Token::Value::ADD, reg) | 539 .BinaryOperation(Token::Value::ADD, reg) |
518 .JumpIfFalse(&near4) | 540 .JumpIfFalse(&near4) |
519 .Bind(&near0) | 541 .Bind(&near0) |
520 .Bind(&near1) | 542 .Bind(&near1) |
521 .Bind(&near2) | 543 .Bind(&near2) |
522 .Bind(&near3) | 544 .Bind(&near3) |
523 .Bind(&near4) | 545 .Bind(&near4) |
524 .Jump(&far0) | 546 .Jump(&far0) |
| 547 .Bind(&after_jump1) |
525 .CompareOperation(Token::Value::EQ, reg) | 548 .CompareOperation(Token::Value::EQ, reg) |
526 .JumpIfTrue(&far1) | 549 .JumpIfTrue(&far1) |
527 .CompareOperation(Token::Value::EQ, reg) | 550 .CompareOperation(Token::Value::EQ, reg) |
528 .JumpIfFalse(&far2) | 551 .JumpIfFalse(&far2) |
529 .BinaryOperation(Token::Value::ADD, reg) | 552 .BinaryOperation(Token::Value::ADD, reg) |
530 .JumpIfTrue(&far3) | 553 .JumpIfTrue(&far3) |
531 .BinaryOperation(Token::Value::ADD, reg) | 554 .BinaryOperation(Token::Value::ADD, reg) |
532 .JumpIfFalse(&far4); | 555 .JumpIfFalse(&far4); |
533 for (int i = 0; i < kFarJumpDistance - 18; i++) { | 556 for (int i = 0; i < kFarJumpDistance - 18; i++) { |
534 builder.Debugger(); | 557 builder.Debugger(); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
630 .Bind(&label2) | 653 .Bind(&label2) |
631 .CompareOperation(Token::Value::EQ, reg) | 654 .CompareOperation(Token::Value::EQ, reg) |
632 .JumpIfFalse(&label2) | 655 .JumpIfFalse(&label2) |
633 .Bind(&label3) | 656 .Bind(&label3) |
634 .BinaryOperation(Token::Value::ADD, reg) | 657 .BinaryOperation(Token::Value::ADD, reg) |
635 .JumpIfTrue(&label3) | 658 .JumpIfTrue(&label3) |
636 .Bind(&label4) | 659 .Bind(&label4) |
637 .BinaryOperation(Token::Value::ADD, reg) | 660 .BinaryOperation(Token::Value::ADD, reg) |
638 .JumpIfFalse(&label4); | 661 .JumpIfFalse(&label4); |
639 for (int i = 0; i < 63; i++) { | 662 for (int i = 0; i < 63; i++) { |
640 builder.Jump(&label4); | 663 BytecodeLabel after_jump; |
| 664 builder.Jump(&label4).Bind(&after_jump); |
641 } | 665 } |
642 | 666 |
643 // Add padding to force wide backwards jumps. | 667 // Add padding to force wide backwards jumps. |
644 for (int i = 0; i < 256; i++) { | 668 for (int i = 0; i < 256; i++) { |
645 builder.Debugger(); | 669 builder.Debugger(); |
646 } | 670 } |
647 | 671 |
648 builder.BinaryOperation(Token::Value::ADD, reg).JumpIfFalse(&label4); | 672 builder.BinaryOperation(Token::Value::ADD, reg).JumpIfFalse(&label4); |
649 builder.BinaryOperation(Token::Value::ADD, reg).JumpIfTrue(&label3); | 673 builder.BinaryOperation(Token::Value::ADD, reg).JumpIfTrue(&label3); |
650 builder.CompareOperation(Token::Value::EQ, reg).JumpIfFalse(&label2); | 674 builder.CompareOperation(Token::Value::EQ, reg).JumpIfFalse(&label2); |
651 builder.CompareOperation(Token::Value::EQ, reg).JumpIfTrue(&label1); | 675 builder.CompareOperation(Token::Value::EQ, reg).JumpIfTrue(&label1); |
652 builder.Jump(&label0); | 676 builder.Jump(&label0); |
| 677 BytecodeLabel end; |
| 678 builder.Bind(&end); |
653 builder.Return(); | 679 builder.Return(); |
654 | 680 |
655 Handle<BytecodeArray> array = builder.ToBytecodeArray(); | 681 Handle<BytecodeArray> array = builder.ToBytecodeArray(); |
656 BytecodeArrayIterator iterator(array); | 682 BytecodeArrayIterator iterator(array); |
657 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 683 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
658 CHECK_EQ(iterator.GetImmediateOperand(0), 0); | 684 CHECK_EQ(iterator.GetImmediateOperand(0), 0); |
659 iterator.Advance(); | 685 iterator.Advance(); |
660 // Ignore compare operation. | 686 // Ignore compare operation. |
661 iterator.Advance(); | 687 iterator.Advance(); |
662 CHECK_EQ(iterator.current_bytecode(), | 688 CHECK_EQ(iterator.current_bytecode(), |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
728 iterator.Advance(); | 754 iterator.Advance(); |
729 CHECK(iterator.done()); | 755 CHECK(iterator.done()); |
730 } | 756 } |
731 | 757 |
732 | 758 |
733 TEST_F(BytecodeArrayBuilderTest, LabelReuse) { | 759 TEST_F(BytecodeArrayBuilderTest, LabelReuse) { |
734 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0); | 760 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0); |
735 | 761 |
736 // Labels can only have 1 forward reference, but | 762 // Labels can only have 1 forward reference, but |
737 // can be referred to mulitple times once bound. | 763 // can be referred to mulitple times once bound. |
738 BytecodeLabel label; | 764 BytecodeLabel label, after_jump0, after_jump1; |
739 | 765 |
740 builder.Jump(&label).Bind(&label).Jump(&label).Jump(&label).Return(); | 766 builder.Jump(&label) |
| 767 .Bind(&label) |
| 768 .Jump(&label) |
| 769 .Bind(&after_jump0) |
| 770 .Jump(&label) |
| 771 .Bind(&after_jump1) |
| 772 .Return(); |
741 | 773 |
742 Handle<BytecodeArray> array = builder.ToBytecodeArray(); | 774 Handle<BytecodeArray> array = builder.ToBytecodeArray(); |
743 BytecodeArrayIterator iterator(array); | 775 BytecodeArrayIterator iterator(array); |
744 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 776 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
745 CHECK_EQ(iterator.GetImmediateOperand(0), 2); | 777 CHECK_EQ(iterator.GetImmediateOperand(0), 2); |
746 iterator.Advance(); | 778 iterator.Advance(); |
747 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 779 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
748 CHECK_EQ(iterator.GetImmediateOperand(0), 0); | 780 CHECK_EQ(iterator.GetImmediateOperand(0), 0); |
749 iterator.Advance(); | 781 iterator.Advance(); |
750 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 782 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
751 CHECK_EQ(iterator.GetImmediateOperand(0), -2); | 783 CHECK_EQ(iterator.GetImmediateOperand(0), -2); |
752 iterator.Advance(); | 784 iterator.Advance(); |
753 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 785 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
754 iterator.Advance(); | 786 iterator.Advance(); |
755 CHECK(iterator.done()); | 787 CHECK(iterator.done()); |
756 } | 788 } |
757 | 789 |
758 | 790 |
759 TEST_F(BytecodeArrayBuilderTest, LabelAddressReuse) { | 791 TEST_F(BytecodeArrayBuilderTest, LabelAddressReuse) { |
760 static const int kRepeats = 3; | 792 static const int kRepeats = 3; |
761 | 793 |
762 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0); | 794 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0); |
763 for (int i = 0; i < kRepeats; i++) { | 795 for (int i = 0; i < kRepeats; i++) { |
764 BytecodeLabel label; | 796 BytecodeLabel label, after_jump0, after_jump1; |
765 builder.Jump(&label).Bind(&label).Jump(&label).Jump(&label); | 797 builder.Jump(&label) |
| 798 .Bind(&label) |
| 799 .Jump(&label) |
| 800 .Bind(&after_jump0) |
| 801 .Jump(&label) |
| 802 .Bind(&after_jump1); |
766 } | 803 } |
767 builder.Return(); | 804 builder.Return(); |
768 | 805 |
769 Handle<BytecodeArray> array = builder.ToBytecodeArray(); | 806 Handle<BytecodeArray> array = builder.ToBytecodeArray(); |
770 BytecodeArrayIterator iterator(array); | 807 BytecodeArrayIterator iterator(array); |
771 for (int i = 0; i < kRepeats; i++) { | 808 for (int i = 0; i < kRepeats; i++) { |
772 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 809 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
773 CHECK_EQ(iterator.GetImmediateOperand(0), 2); | 810 CHECK_EQ(iterator.GetImmediateOperand(0), 2); |
774 iterator.Advance(); | 811 iterator.Advance(); |
775 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 812 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
776 CHECK_EQ(iterator.GetImmediateOperand(0), 0); | 813 CHECK_EQ(iterator.GetImmediateOperand(0), 0); |
777 iterator.Advance(); | 814 iterator.Advance(); |
778 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 815 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
779 CHECK_EQ(iterator.GetImmediateOperand(0), -2); | 816 CHECK_EQ(iterator.GetImmediateOperand(0), -2); |
780 iterator.Advance(); | 817 iterator.Advance(); |
781 } | 818 } |
782 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 819 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
783 iterator.Advance(); | 820 iterator.Advance(); |
784 CHECK(iterator.done()); | 821 CHECK(iterator.done()); |
785 } | 822 } |
786 | 823 |
787 } // namespace interpreter | 824 } // namespace interpreter |
788 } // namespace internal | 825 } // namespace internal |
789 } // namespace v8 | 826 } // namespace v8 |
OLD | NEW |