blob: 084a0b4f15ee730f9c6e71ba8a1d596fefe49a9f [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 Murdochb8e0da22011-05-16 14:20:40 +010031#include "heap.h"
Steve Block44f0eee2011-05-26 01:26:41 +010032#include "v8memory.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010033#include "zone.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010034
35namespace v8 {
36namespace internal {
37
Ben Murdochb8e0da22011-05-16 14:20:40 +010038struct Register;
39
40class SafepointEntry BASE_EMBEDDED {
41 public:
42 SafepointEntry() : info_(0), bits_(NULL) {}
43
44 SafepointEntry(unsigned info, uint8_t* bits) : info_(info), bits_(bits) {
45 ASSERT(is_valid());
46 }
47
48 bool is_valid() const { return bits_ != NULL; }
49
50 bool Equals(const SafepointEntry& other) const {
51 return info_ == other.info_ && bits_ == other.bits_;
52 }
53
54 void Reset() {
55 info_ = 0;
56 bits_ = NULL;
57 }
58
59 int deoptimization_index() const {
60 ASSERT(is_valid());
61 return DeoptimizationIndexField::decode(info_);
62 }
63
64 int gap_code_size() const {
65 ASSERT(is_valid());
66 return GapCodeSizeField::decode(info_);
67 }
68
69 int argument_count() const {
70 ASSERT(is_valid());
71 return ArgumentsField::decode(info_);
72 }
73
74 bool has_doubles() const {
75 ASSERT(is_valid());
76 return SaveDoublesField::decode(info_);
77 }
78
79 uint8_t* bits() {
80 ASSERT(is_valid());
81 return bits_;
82 }
83
84 bool HasRegisters() const;
85 bool HasRegisterAt(int reg_index) const;
86
87 // Reserve 13 bits for the gap code size. On ARM a constant pool can be
88 // emitted when generating the gap code. The size of the const pool is less
89 // than what can be represented in 12 bits, so 13 bits gives room for having
90 // instructions before potentially emitting a constant pool.
91 static const int kGapCodeSizeBits = 13;
92 static const int kArgumentsFieldBits = 3;
93 static const int kSaveDoublesFieldBits = 1;
94 static const int kDeoptIndexBits =
95 32 - kGapCodeSizeBits - kArgumentsFieldBits - kSaveDoublesFieldBits;
96 class GapCodeSizeField: public BitField<unsigned, 0, kGapCodeSizeBits> {};
97 class DeoptimizationIndexField: public BitField<int,
98 kGapCodeSizeBits,
99 kDeoptIndexBits> {}; // NOLINT
100 class ArgumentsField: public BitField<unsigned,
101 kGapCodeSizeBits + kDeoptIndexBits,
102 kArgumentsFieldBits> {}; // NOLINT
103 class SaveDoublesField: public BitField<bool,
104 kGapCodeSizeBits + kDeoptIndexBits +
105 kArgumentsFieldBits,
106 kSaveDoublesFieldBits> { }; // NOLINT
107
108 private:
109 unsigned info_;
110 uint8_t* bits_;
111};
112
113
Ben Murdochb0fe1622011-05-05 13:52:32 +0100114class SafepointTable BASE_EMBEDDED {
115 public:
116 explicit SafepointTable(Code* code);
117
118 int size() const {
119 return kHeaderSize +
120 (length_ * (kPcAndDeoptimizationIndexSize + entry_size_)); }
121 unsigned length() const { return length_; }
122 unsigned entry_size() const { return entry_size_; }
123
124 unsigned GetPcOffset(unsigned index) const {
125 ASSERT(index < length_);
126 return Memory::uint32_at(GetPcOffsetLocation(index));
127 }
128
Ben Murdochb8e0da22011-05-16 14:20:40 +0100129 SafepointEntry GetEntry(unsigned index) const {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100130 ASSERT(index < length_);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100131 unsigned info = Memory::uint32_at(GetInfoLocation(index));
132 uint8_t* bits = &Memory::uint8_at(entries_ + (index * entry_size_));
133 return SafepointEntry(info, bits);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100134 }
135
Ben Murdochb8e0da22011-05-16 14:20:40 +0100136 // Returns the entry for the given pc.
137 SafepointEntry FindEntry(Address pc) const;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100138
139 void PrintEntry(unsigned index) const;
140
141 private:
142 static const uint8_t kNoRegisters = 0xFF;
143
144 static const int kLengthOffset = 0;
145 static const int kEntrySizeOffset = kLengthOffset + kIntSize;
146 static const int kHeaderSize = kEntrySizeOffset + kIntSize;
147
148 static const int kPcSize = kIntSize;
149 static const int kDeoptimizationIndexSize = kIntSize;
150 static const int kPcAndDeoptimizationIndexSize =
151 kPcSize + kDeoptimizationIndexSize;
152
153 Address GetPcOffsetLocation(unsigned index) const {
154 return pc_and_deoptimization_indexes_ +
155 (index * kPcAndDeoptimizationIndexSize);
156 }
157
Ben Murdochb8e0da22011-05-16 14:20:40 +0100158 Address GetInfoLocation(unsigned index) const {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100159 return GetPcOffsetLocation(index) + kPcSize;
160 }
161
162 static void PrintBits(uint8_t byte, int digits);
163
164 AssertNoAllocation no_allocation_;
165 Code* code_;
166 unsigned length_;
167 unsigned entry_size_;
168
169 Address pc_and_deoptimization_indexes_;
170 Address entries_;
171
172 friend class SafepointTableBuilder;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100173 friend class SafepointEntry;
174
175 DISALLOW_COPY_AND_ASSIGN(SafepointTable);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100176};
177
178
179class Safepoint BASE_EMBEDDED {
180 public:
Steve Block1e0659c2011-05-24 12:43:12 +0100181 typedef enum {
182 kSimple = 0,
183 kWithRegisters = 1 << 0,
184 kWithDoubles = 1 << 1,
185 kWithRegistersAndDoubles = kWithRegisters | kWithDoubles
186 } Kind;
187
Ben Murdochb8e0da22011-05-16 14:20:40 +0100188 static const int kNoDeoptimizationIndex =
189 (1 << (SafepointEntry::kDeoptIndexBits)) - 1;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100190
191 void DefinePointerSlot(int index) { indexes_->Add(index); }
Ben Murdochb8e0da22011-05-16 14:20:40 +0100192 void DefinePointerRegister(Register reg);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100193
194 private:
195 Safepoint(ZoneList<int>* indexes, ZoneList<int>* registers) :
196 indexes_(indexes), registers_(registers) { }
197 ZoneList<int>* indexes_;
198 ZoneList<int>* registers_;
199
200 friend class SafepointTableBuilder;
201};
202
203
204class SafepointTableBuilder BASE_EMBEDDED {
205 public:
206 SafepointTableBuilder()
207 : deoptimization_info_(32),
208 indexes_(32),
209 registers_(32),
210 emitted_(false) { }
211
212 // Get the offset of the emitted safepoint table in the code.
213 unsigned GetCodeOffset() const;
214
215 // Define a new safepoint for the current position in the body.
Steve Block1e0659c2011-05-24 12:43:12 +0100216 Safepoint DefineSafepoint(Assembler* assembler,
217 Safepoint::Kind kind,
218 int arguments,
219 int deoptimization_index);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100220
Steve Block1e0659c2011-05-24 12:43:12 +0100221 // Update the last safepoint with the size of the code generated until the
222 // end of the gap following it.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100223 void SetPcAfterGap(int pc) {
224 ASSERT(!deoptimization_info_.is_empty());
225 int index = deoptimization_info_.length() - 1;
226 deoptimization_info_[index].pc_after_gap = pc;
227 }
228
Steve Block44f0eee2011-05-26 01:26:41 +0100229 // Get the end pc offset of the last safepoint, including the code generated
230 // until the end of the gap following it.
231 unsigned GetPcAfterGap() {
232 int index = deoptimization_info_.length();
233 if (index == 0) return 0;
234 return deoptimization_info_[index - 1].pc_after_gap;
235 }
236
Ben Murdochb0fe1622011-05-05 13:52:32 +0100237 // Emit the safepoint table after the body. The number of bits per
238 // entry must be enough to hold all the pointer indexes.
239 void Emit(Assembler* assembler, int bits_per_entry);
240
Steve Block1e0659c2011-05-24 12:43:12 +0100241 // Count the number of deoptimization points where the next
242 // following deoptimization point comes less than limit bytes
243 // after the end of this point's gap.
244 int CountShortDeoptimizationIntervals(unsigned limit);
245
Ben Murdochb0fe1622011-05-05 13:52:32 +0100246 private:
247 struct DeoptimizationInfo {
248 unsigned pc;
249 unsigned deoptimization_index;
250 unsigned pc_after_gap;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100251 unsigned arguments;
252 bool has_doubles;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100253 };
254
Ben Murdochb8e0da22011-05-16 14:20:40 +0100255 uint32_t EncodeExceptPC(const DeoptimizationInfo& info);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100256
257 ZoneList<DeoptimizationInfo> deoptimization_info_;
258 ZoneList<ZoneList<int>*> indexes_;
259 ZoneList<ZoneList<int>*> registers_;
260
Ben Murdochb0fe1622011-05-05 13:52:32 +0100261 unsigned offset_;
Steve Block1e0659c2011-05-24 12:43:12 +0100262 bool emitted_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100263
264 DISALLOW_COPY_AND_ASSIGN(SafepointTableBuilder);
265};
266
267} } // namespace v8::internal
268
269#endif // V8_SAFEPOINT_TABLE_H_