blob: de537f98284c73fd5faf502859e9ae8b3c495d6a [file] [log] [blame]
Steve Block1e0659c2011-05-24 12:43:12 +01001// Copyright 2011 the V8 project authors. All rights reserved.
Ben Murdochb0fe1622011-05-05 13:52:32 +01002// 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
Ben Murdoch257744e2011-11-30 15:57:28 +000031#include "allocation.h"
Ben Murdochb8e0da22011-05-16 14:20:40 +010032#include "heap.h"
Steve Block44f0eee2011-05-26 01:26:41 +010033#include "v8memory.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010034#include "zone.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010035
36namespace v8 {
37namespace internal {
38
Ben Murdochb8e0da22011-05-16 14:20:40 +010039struct Register;
40
41class SafepointEntry BASE_EMBEDDED {
42 public:
43 SafepointEntry() : info_(0), bits_(NULL) {}
44
45 SafepointEntry(unsigned info, uint8_t* bits) : info_(info), bits_(bits) {
46 ASSERT(is_valid());
47 }
48
49 bool is_valid() const { return bits_ != NULL; }
50
51 bool Equals(const SafepointEntry& other) const {
52 return info_ == other.info_ && bits_ == other.bits_;
53 }
54
55 void Reset() {
56 info_ = 0;
57 bits_ = NULL;
58 }
59
60 int deoptimization_index() const {
61 ASSERT(is_valid());
62 return DeoptimizationIndexField::decode(info_);
63 }
64
65 int gap_code_size() const {
66 ASSERT(is_valid());
67 return GapCodeSizeField::decode(info_);
68 }
69
70 int argument_count() const {
71 ASSERT(is_valid());
72 return ArgumentsField::decode(info_);
73 }
74
75 bool has_doubles() const {
76 ASSERT(is_valid());
77 return SaveDoublesField::decode(info_);
78 }
79
80 uint8_t* bits() {
81 ASSERT(is_valid());
82 return bits_;
83 }
84
85 bool HasRegisters() const;
86 bool HasRegisterAt(int reg_index) const;
87
88 // Reserve 13 bits for the gap code size. On ARM a constant pool can be
89 // emitted when generating the gap code. The size of the const pool is less
90 // than what can be represented in 12 bits, so 13 bits gives room for having
91 // instructions before potentially emitting a constant pool.
92 static const int kGapCodeSizeBits = 13;
93 static const int kArgumentsFieldBits = 3;
94 static const int kSaveDoublesFieldBits = 1;
95 static const int kDeoptIndexBits =
96 32 - kGapCodeSizeBits - kArgumentsFieldBits - kSaveDoublesFieldBits;
97 class GapCodeSizeField: public BitField<unsigned, 0, kGapCodeSizeBits> {};
98 class DeoptimizationIndexField: public BitField<int,
99 kGapCodeSizeBits,
100 kDeoptIndexBits> {}; // NOLINT
101 class ArgumentsField: public BitField<unsigned,
102 kGapCodeSizeBits + kDeoptIndexBits,
103 kArgumentsFieldBits> {}; // NOLINT
104 class SaveDoublesField: public BitField<bool,
105 kGapCodeSizeBits + kDeoptIndexBits +
106 kArgumentsFieldBits,
107 kSaveDoublesFieldBits> { }; // NOLINT
108
109 private:
110 unsigned info_;
111 uint8_t* bits_;
112};
113
114
Ben Murdochb0fe1622011-05-05 13:52:32 +0100115class SafepointTable BASE_EMBEDDED {
116 public:
117 explicit SafepointTable(Code* code);
118
119 int size() const {
120 return kHeaderSize +
121 (length_ * (kPcAndDeoptimizationIndexSize + entry_size_)); }
122 unsigned length() const { return length_; }
123 unsigned entry_size() const { return entry_size_; }
124
125 unsigned GetPcOffset(unsigned index) const {
126 ASSERT(index < length_);
127 return Memory::uint32_at(GetPcOffsetLocation(index));
128 }
129
Ben Murdochb8e0da22011-05-16 14:20:40 +0100130 SafepointEntry GetEntry(unsigned index) const {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100131 ASSERT(index < length_);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100132 unsigned info = Memory::uint32_at(GetInfoLocation(index));
133 uint8_t* bits = &Memory::uint8_at(entries_ + (index * entry_size_));
134 return SafepointEntry(info, bits);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100135 }
136
Ben Murdochb8e0da22011-05-16 14:20:40 +0100137 // Returns the entry for the given pc.
138 SafepointEntry FindEntry(Address pc) const;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100139
140 void PrintEntry(unsigned index) const;
141
142 private:
143 static const uint8_t kNoRegisters = 0xFF;
144
145 static const int kLengthOffset = 0;
146 static const int kEntrySizeOffset = kLengthOffset + kIntSize;
147 static const int kHeaderSize = kEntrySizeOffset + kIntSize;
148
149 static const int kPcSize = kIntSize;
150 static const int kDeoptimizationIndexSize = kIntSize;
151 static const int kPcAndDeoptimizationIndexSize =
152 kPcSize + kDeoptimizationIndexSize;
153
154 Address GetPcOffsetLocation(unsigned index) const {
155 return pc_and_deoptimization_indexes_ +
156 (index * kPcAndDeoptimizationIndexSize);
157 }
158
Ben Murdochb8e0da22011-05-16 14:20:40 +0100159 Address GetInfoLocation(unsigned index) const {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100160 return GetPcOffsetLocation(index) + kPcSize;
161 }
162
163 static void PrintBits(uint8_t byte, int digits);
164
165 AssertNoAllocation no_allocation_;
166 Code* code_;
167 unsigned length_;
168 unsigned entry_size_;
169
170 Address pc_and_deoptimization_indexes_;
171 Address entries_;
172
173 friend class SafepointTableBuilder;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100174 friend class SafepointEntry;
175
176 DISALLOW_COPY_AND_ASSIGN(SafepointTable);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100177};
178
179
180class Safepoint BASE_EMBEDDED {
181 public:
Steve Block1e0659c2011-05-24 12:43:12 +0100182 typedef enum {
183 kSimple = 0,
184 kWithRegisters = 1 << 0,
185 kWithDoubles = 1 << 1,
186 kWithRegistersAndDoubles = kWithRegisters | kWithDoubles
187 } Kind;
188
Ben Murdochb8e0da22011-05-16 14:20:40 +0100189 static const int kNoDeoptimizationIndex =
190 (1 << (SafepointEntry::kDeoptIndexBits)) - 1;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100191
192 void DefinePointerSlot(int index) { indexes_->Add(index); }
Ben Murdochb8e0da22011-05-16 14:20:40 +0100193 void DefinePointerRegister(Register reg);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100194
195 private:
196 Safepoint(ZoneList<int>* indexes, ZoneList<int>* registers) :
197 indexes_(indexes), registers_(registers) { }
198 ZoneList<int>* indexes_;
199 ZoneList<int>* registers_;
200
201 friend class SafepointTableBuilder;
202};
203
204
205class SafepointTableBuilder BASE_EMBEDDED {
206 public:
207 SafepointTableBuilder()
208 : deoptimization_info_(32),
209 indexes_(32),
210 registers_(32),
211 emitted_(false) { }
212
213 // Get the offset of the emitted safepoint table in the code.
214 unsigned GetCodeOffset() const;
215
216 // Define a new safepoint for the current position in the body.
Steve Block1e0659c2011-05-24 12:43:12 +0100217 Safepoint DefineSafepoint(Assembler* assembler,
218 Safepoint::Kind kind,
219 int arguments,
220 int deoptimization_index);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100221
Steve Block1e0659c2011-05-24 12:43:12 +0100222 // Update the last safepoint with the size of the code generated until the
223 // end of the gap following it.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100224 void SetPcAfterGap(int pc) {
225 ASSERT(!deoptimization_info_.is_empty());
226 int index = deoptimization_info_.length() - 1;
227 deoptimization_info_[index].pc_after_gap = pc;
228 }
229
Steve Block44f0eee2011-05-26 01:26:41 +0100230 // Get the end pc offset of the last safepoint, including the code generated
231 // until the end of the gap following it.
232 unsigned GetPcAfterGap() {
233 int index = deoptimization_info_.length();
234 if (index == 0) return 0;
235 return deoptimization_info_[index - 1].pc_after_gap;
236 }
237
Ben Murdochb0fe1622011-05-05 13:52:32 +0100238 // Emit the safepoint table after the body. The number of bits per
239 // entry must be enough to hold all the pointer indexes.
240 void Emit(Assembler* assembler, int bits_per_entry);
241
Steve Block1e0659c2011-05-24 12:43:12 +0100242 // Count the number of deoptimization points where the next
243 // following deoptimization point comes less than limit bytes
244 // after the end of this point's gap.
245 int CountShortDeoptimizationIntervals(unsigned limit);
246
Ben Murdochb0fe1622011-05-05 13:52:32 +0100247 private:
248 struct DeoptimizationInfo {
249 unsigned pc;
250 unsigned deoptimization_index;
251 unsigned pc_after_gap;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100252 unsigned arguments;
253 bool has_doubles;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100254 };
255
Ben Murdochb8e0da22011-05-16 14:20:40 +0100256 uint32_t EncodeExceptPC(const DeoptimizationInfo& info);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100257
258 ZoneList<DeoptimizationInfo> deoptimization_info_;
259 ZoneList<ZoneList<int>*> indexes_;
260 ZoneList<ZoneList<int>*> registers_;
261
Ben Murdochb0fe1622011-05-05 13:52:32 +0100262 unsigned offset_;
Steve Block1e0659c2011-05-24 12:43:12 +0100263 bool emitted_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100264
265 DISALLOW_COPY_AND_ASSIGN(SafepointTableBuilder);
266};
267
268} } // namespace v8::internal
269
270#endif // V8_SAFEPOINT_TABLE_H_