| 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 |