Allow arguments in safepoints with registers.
[platform/upstream/v8.git] / src / safepoint-table.h
1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #ifndef V8_SAFEPOINT_TABLE_H_
29 #define V8_SAFEPOINT_TABLE_H_
30
31 #include "v8.h"
32
33 #include "heap.h"
34 #include "zone.h"
35 #include "zone-inl.h"
36
37 namespace v8 {
38 namespace internal {
39
40 struct Register;
41
42 class SafepointEntry BASE_EMBEDDED {
43  public:
44   SafepointEntry() : info_(0), bits_(NULL) {}
45
46   SafepointEntry(unsigned info, uint8_t* bits) : info_(info), bits_(bits) {
47     ASSERT(is_valid());
48   }
49
50   bool is_valid() const { return bits_ != NULL; }
51
52   bool Equals(const SafepointEntry& other) const {
53     return info_ == other.info_ && bits_ == other.bits_;
54   }
55
56   void Reset() {
57     info_ = 0;
58     bits_ = NULL;
59   }
60
61   int deoptimization_index() const {
62     ASSERT(is_valid());
63     return DeoptimizationIndexField::decode(info_);
64   }
65
66   int gap_code_size() const {
67     ASSERT(is_valid());
68     return GapCodeSizeField::decode(info_);
69   }
70
71   int argument_count() const {
72     ASSERT(is_valid());
73     return ArgumentsField::decode(info_);
74   }
75
76   uint8_t* bits() {
77     ASSERT(is_valid());
78     return bits_;
79   }
80
81   bool HasRegisters() const;
82   bool HasRegisterAt(int reg_index) const;
83
84   // Reserve 13 bits for the gap code size. On ARM a constant pool can be
85   // emitted when generating the gap code. The size of the const pool is less
86   // than what can be represented in 12 bits, so 13 bits gives room for having
87   // instructions before potentially emitting a constant pool.
88   static const int kGapCodeSizeBits = 13;
89   static const int kArgumentsFieldBits = 3;
90   static const int kDeoptIndexBits =
91       32 - kGapCodeSizeBits - kArgumentsFieldBits;
92   class GapCodeSizeField: public BitField<unsigned, 0, kGapCodeSizeBits> {};
93   class DeoptimizationIndexField: public BitField<int,
94                                                   kGapCodeSizeBits,
95                                                   kDeoptIndexBits> {};  // NOLINT
96   class ArgumentsField: public BitField<unsigned,
97                                         kGapCodeSizeBits + kDeoptIndexBits,
98                                         kArgumentsFieldBits> {};  // NOLINT
99  private:
100   unsigned info_;
101   uint8_t* bits_;
102 };
103
104
105 class SafepointTable BASE_EMBEDDED {
106  public:
107   explicit SafepointTable(Code* code);
108
109   int size() const {
110     return kHeaderSize +
111            (length_ * (kPcAndDeoptimizationIndexSize + entry_size_)); }
112   unsigned length() const { return length_; }
113   unsigned entry_size() const { return entry_size_; }
114
115   unsigned GetPcOffset(unsigned index) const {
116     ASSERT(index < length_);
117     return Memory::uint32_at(GetPcOffsetLocation(index));
118   }
119
120   SafepointEntry GetEntry(unsigned index) const {
121     ASSERT(index < length_);
122     unsigned info = Memory::uint32_at(GetInfoLocation(index));
123     uint8_t* bits = &Memory::uint8_at(entries_ + (index * entry_size_));
124     return SafepointEntry(info, bits);
125   }
126
127   // Returns the entry for the given pc.
128   SafepointEntry FindEntry(Address pc) const;
129
130   void PrintEntry(unsigned index) const;
131
132  private:
133   static const uint8_t kNoRegisters = 0xFF;
134
135   static const int kLengthOffset = 0;
136   static const int kEntrySizeOffset = kLengthOffset + kIntSize;
137   static const int kHeaderSize = kEntrySizeOffset + kIntSize;
138
139   static const int kPcSize = kIntSize;
140   static const int kDeoptimizationIndexSize = kIntSize;
141   static const int kPcAndDeoptimizationIndexSize =
142       kPcSize + kDeoptimizationIndexSize;
143
144   Address GetPcOffsetLocation(unsigned index) const {
145     return pc_and_deoptimization_indexes_ +
146            (index * kPcAndDeoptimizationIndexSize);
147   }
148
149   Address GetInfoLocation(unsigned index) const {
150     return GetPcOffsetLocation(index) + kPcSize;
151   }
152
153   static void PrintBits(uint8_t byte, int digits);
154
155   AssertNoAllocation no_allocation_;
156   Code* code_;
157   unsigned length_;
158   unsigned entry_size_;
159
160   Address pc_and_deoptimization_indexes_;
161   Address entries_;
162
163   friend class SafepointTableBuilder;
164   friend class SafepointEntry;
165
166   DISALLOW_COPY_AND_ASSIGN(SafepointTable);
167 };
168
169
170 class Safepoint BASE_EMBEDDED {
171  public:
172   static const int kNoDeoptimizationIndex =
173       (1 << (SafepointEntry::kDeoptIndexBits)) - 1;
174
175   void DefinePointerSlot(int index) { indexes_->Add(index); }
176   void DefinePointerRegister(Register reg);
177
178  private:
179   Safepoint(ZoneList<int>* indexes, ZoneList<int>* registers) :
180       indexes_(indexes), registers_(registers) { }
181   ZoneList<int>* indexes_;
182   ZoneList<int>* registers_;
183
184   friend class SafepointTableBuilder;
185 };
186
187
188 class SafepointTableBuilder BASE_EMBEDDED {
189  public:
190   SafepointTableBuilder()
191       : deoptimization_info_(32),
192         indexes_(32),
193         registers_(32),
194         emitted_(false) { }
195
196   // Get the offset of the emitted safepoint table in the code.
197   unsigned GetCodeOffset() const;
198
199   // Define a new safepoint for the current position in the body.
200   Safepoint DefineSafepoint(
201       Assembler* assembler,
202       int deoptimization_index = Safepoint::kNoDeoptimizationIndex);
203
204   // Define a new safepoint with registers on the stack for the
205   // current position in the body and take the number of arguments on
206   // top of the registers into account.
207   Safepoint DefineSafepointWithRegisters(
208       Assembler* assembler,
209       int arguments,
210       int deoptimization_index = Safepoint::kNoDeoptimizationIndex);
211
212   // Update the last safepoint with the size of the code generated for the gap
213   // following it.
214   void SetPcAfterGap(int pc) {
215     ASSERT(!deoptimization_info_.is_empty());
216     int index = deoptimization_info_.length() - 1;
217     deoptimization_info_[index].pc_after_gap = pc;
218   }
219
220   // Emit the safepoint table after the body. The number of bits per
221   // entry must be enough to hold all the pointer indexes.
222   void Emit(Assembler* assembler, int bits_per_entry);
223
224  private:
225   struct DeoptimizationInfo {
226     unsigned pc;
227     unsigned deoptimization_index;
228     unsigned pc_after_gap;
229     unsigned arguments;
230   };
231
232   uint32_t EncodeExceptPC(const DeoptimizationInfo& info);
233
234   ZoneList<DeoptimizationInfo> deoptimization_info_;
235   ZoneList<ZoneList<int>*> indexes_;
236   ZoneList<ZoneList<int>*> registers_;
237
238   bool emitted_;
239   unsigned offset_;
240
241   DISALLOW_COPY_AND_ASSIGN(SafepointTableBuilder);
242 };
243
244 } }  // namespace v8::internal
245
246 #endif  // V8_SAFEPOINT_TABLE_H_