OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 18 matching lines...) Expand all Loading... |
29 | 29 |
30 #include "codegen.h" | 30 #include "codegen.h" |
31 #include "deoptimizer.h" | 31 #include "deoptimizer.h" |
32 #include "full-codegen.h" | 32 #include "full-codegen.h" |
33 #include "safepoint-table.h" | 33 #include "safepoint-table.h" |
34 | 34 |
35 namespace v8 { | 35 namespace v8 { |
36 namespace internal { | 36 namespace internal { |
37 | 37 |
38 | 38 |
39 const int Deoptimizer::table_entry_size_ = 32; | |
40 | |
41 | |
42 int Deoptimizer::patch_size() { | 39 int Deoptimizer::patch_size() { |
43 const int kCallInstructionSizeInWords = 4; | 40 const int kCallInstructionSizeInWords = 4; |
44 return kCallInstructionSizeInWords * Assembler::kInstrSize; | 41 return kCallInstructionSizeInWords * Assembler::kInstrSize; |
45 } | 42 } |
46 | 43 |
47 | 44 |
48 void Deoptimizer::DeoptimizeFunction(JSFunction* function) { | 45 void Deoptimizer::DeoptimizeFunction(JSFunction* function) { |
49 HandleScope scope; | 46 HandleScope scope; |
50 AssertNoAllocation no_allocation; | 47 AssertNoAllocation no_allocation; |
51 | 48 |
(...skipping 780 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
832 | 829 |
833 __ InitializeRootRegister(); | 830 __ InitializeRootRegister(); |
834 | 831 |
835 __ pop(at); // Get continuation, leave pc on stack. | 832 __ pop(at); // Get continuation, leave pc on stack. |
836 __ pop(ra); | 833 __ pop(ra); |
837 __ Jump(at); | 834 __ Jump(at); |
838 __ stop("Unreachable."); | 835 __ stop("Unreachable."); |
839 } | 836 } |
840 | 837 |
841 | 838 |
| 839 // Maximum size of a table entry generated below. |
| 840 const int Deoptimizer::table_entry_size_ = 12 * Assembler::kInstrSize; |
| 841 |
842 void Deoptimizer::TableEntryGenerator::GeneratePrologue() { | 842 void Deoptimizer::TableEntryGenerator::GeneratePrologue() { |
843 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm()); | 843 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm()); |
844 | 844 |
845 // Create a sequence of deoptimization entries. Note that any | 845 // Create a sequence of deoptimization entries. Note that any |
846 // registers may be still live. | 846 // registers may be still live. |
847 | 847 Label table_start; |
848 Label done; | 848 __ bind(&table_start); |
849 for (int i = 0; i < count(); i++) { | 849 for (int i = 0; i < count(); i++) { |
850 int start = masm()->pc_offset(); | 850 Label start; |
851 USE(start); | 851 __ bind(&start); |
852 if (type() != EAGER) { | 852 if (type() != EAGER) { |
853 // Emulate ia32 like call by pushing return address to stack. | 853 // Emulate ia32 like call by pushing return address to stack. |
854 __ push(ra); | 854 __ addiu(sp, sp, -3 * kPointerSize); |
| 855 __ sw(ra, MemOperand(sp, 2 * kPointerSize)); |
| 856 } else { |
| 857 __ addiu(sp, sp, -2 * kPointerSize); |
855 } | 858 } |
856 __ li(at, Operand(i)); | 859 // Using ori makes sure only one instruction is generated. This will work |
857 __ push(at); | 860 // as long as the number of deopt entries is below 2^16. |
858 __ Branch(&done); | 861 __ ori(at, zero_reg, i); |
| 862 __ sw(at, MemOperand(sp, kPointerSize)); |
| 863 __ sw(ra, MemOperand(sp, 0)); |
| 864 // This branch instruction only jumps over one instruction, and that is |
| 865 // executed in the delay slot. The result is that execution is linear but |
| 866 // the ra register is updated. |
| 867 __ bal(1); |
| 868 // Jump over the remaining deopt entries (including this one). |
| 869 // Only include the remaining part of the current entry in the calculation. |
| 870 const int remaining_entries = (count() - i) * table_entry_size_; |
| 871 const int cur_size = masm()->SizeOfCodeGeneratedSince(&start); |
| 872 // ra points to the instruction after the delay slot. Adjust by 4. |
| 873 __ Addu(at, ra, remaining_entries - cur_size - Assembler::kInstrSize); |
| 874 __ lw(ra, MemOperand(sp, 0)); |
| 875 __ jr(at); // Expose delay slot. |
| 876 __ addiu(sp, sp, kPointerSize); // In delay slot. |
859 | 877 |
860 // Pad the rest of the code. | 878 // Pad the rest of the code. |
861 while (table_entry_size_ > (masm()->pc_offset() - start)) { | 879 while (table_entry_size_ > (masm()->SizeOfCodeGeneratedSince(&start))) { |
862 __ nop(); | 880 __ nop(); |
863 } | 881 } |
864 | 882 |
865 ASSERT_EQ(table_entry_size_, masm()->pc_offset() - start); | 883 ASSERT_EQ(table_entry_size_, masm()->SizeOfCodeGeneratedSince(&start)); |
866 } | 884 } |
867 __ bind(&done); | 885 |
| 886 ASSERT_EQ(masm()->SizeOfCodeGeneratedSince(&table_start), |
| 887 count() * table_entry_size_); |
868 } | 888 } |
869 | 889 |
870 #undef __ | 890 #undef __ |
871 | 891 |
872 | 892 |
873 } } // namespace v8::internal | 893 } } // namespace v8::internal |
OLD | NEW |