V8 Project
safepoint-table.cc
Go to the documentation of this file.
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/v8.h"
6 
7 #include "src/safepoint-table.h"
8 
9 #include "src/deoptimizer.h"
10 #include "src/disasm.h"
11 #include "src/macro-assembler.h"
12 #include "src/ostreams.h"
13 #include "src/zone-inl.h"
14 
15 namespace v8 {
16 namespace internal {
17 
18 
19 bool SafepointEntry::HasRegisters() const {
20  DCHECK(is_valid());
22  const int num_reg_bytes = kNumSafepointRegisters >> kBitsPerByteLog2;
23  for (int i = 0; i < num_reg_bytes; i++) {
24  if (bits_[i] != SafepointTable::kNoRegisters) return true;
25  }
26  return false;
27 }
28 
29 
30 bool SafepointEntry::HasRegisterAt(int reg_index) const {
31  DCHECK(is_valid());
32  DCHECK(reg_index >= 0 && reg_index < kNumSafepointRegisters);
33  int byte_index = reg_index >> kBitsPerByteLog2;
34  int bit_index = reg_index & (kBitsPerByte - 1);
35  return (bits_[byte_index] & (1 << bit_index)) != 0;
36 }
37 
38 
39 SafepointTable::SafepointTable(Code* code) {
40  DCHECK(code->is_crankshafted());
41  code_ = code;
42  Address header = code->instruction_start() + code->safepoint_table_offset();
43  length_ = Memory::uint32_at(header + kLengthOffset);
44  entry_size_ = Memory::uint32_at(header + kEntrySizeOffset);
45  pc_and_deoptimization_indexes_ = header + kHeaderSize;
46  entries_ = pc_and_deoptimization_indexes_ +
47  (length_ * kPcAndDeoptimizationIndexSize);
48  DCHECK(entry_size_ > 0);
49  STATIC_ASSERT(SafepointEntry::DeoptimizationIndexField::kMax ==
50  Safepoint::kNoDeoptimizationIndex);
51 }
52 
53 
54 SafepointEntry SafepointTable::FindEntry(Address pc) const {
55  unsigned pc_offset = static_cast<unsigned>(pc - code_->instruction_start());
56  for (unsigned i = 0; i < length(); i++) {
57  // TODO(kasperl): Replace the linear search with binary search.
58  if (GetPcOffset(i) == pc_offset) return GetEntry(i);
59  }
60  return SafepointEntry();
61 }
62 
63 
64 void SafepointTable::PrintEntry(unsigned index, OStream& os) const { // NOLINT
65  disasm::NameConverter converter;
66  SafepointEntry entry = GetEntry(index);
67  uint8_t* bits = entry.bits();
68 
69  // Print the stack slot bits.
70  if (entry_size_ > 0) {
72  const int first = kNumSafepointRegisters >> kBitsPerByteLog2;
73  int last = entry_size_ - 1;
74  for (int i = first; i < last; i++) PrintBits(os, bits[i], kBitsPerByte);
75  int last_bits = code_->stack_slots() - ((last - first) * kBitsPerByte);
76  PrintBits(os, bits[last], last_bits);
77 
78  // Print the registers (if any).
79  if (!entry.HasRegisters()) return;
80  for (int j = 0; j < kNumSafepointRegisters; j++) {
81  if (entry.HasRegisterAt(j)) {
82  os << " | " << converter.NameOfCPURegister(j);
83  }
84  }
85  }
86 }
87 
88 
89 void SafepointTable::PrintBits(OStream& os, // NOLINT
90  uint8_t byte, int digits) {
91  DCHECK(digits >= 0 && digits <= kBitsPerByte);
92  for (int i = 0; i < digits; i++) {
93  os << (((byte & (1 << i)) == 0) ? "0" : "1");
94  }
95 }
96 
97 
98 void Safepoint::DefinePointerRegister(Register reg, Zone* zone) {
99  registers_->Add(reg.code(), zone);
100 }
101 
102 
103 Safepoint SafepointTableBuilder::DefineSafepoint(
104  Assembler* assembler,
105  Safepoint::Kind kind,
106  int arguments,
107  Safepoint::DeoptMode deopt_mode) {
108  DCHECK(arguments >= 0);
109  DeoptimizationInfo info;
110  info.pc = assembler->pc_offset();
111  info.arguments = arguments;
112  info.has_doubles = (kind & Safepoint::kWithDoubles);
113  deoptimization_info_.Add(info, zone_);
114  deopt_index_list_.Add(Safepoint::kNoDeoptimizationIndex, zone_);
115  if (deopt_mode == Safepoint::kNoLazyDeopt) {
116  last_lazy_safepoint_ = deopt_index_list_.length();
117  }
118  indexes_.Add(new(zone_) ZoneList<int>(8, zone_), zone_);
119  registers_.Add((kind & Safepoint::kWithRegisters)
120  ? new(zone_) ZoneList<int>(4, zone_)
121  : NULL,
122  zone_);
123  return Safepoint(indexes_.last(), registers_.last());
124 }
125 
126 
127 void SafepointTableBuilder::RecordLazyDeoptimizationIndex(int index) {
128  while (last_lazy_safepoint_ < deopt_index_list_.length()) {
129  deopt_index_list_[last_lazy_safepoint_++] = index;
130  }
131 }
132 
133 unsigned SafepointTableBuilder::GetCodeOffset() const {
134  DCHECK(emitted_);
135  return offset_;
136 }
137 
138 
139 void SafepointTableBuilder::Emit(Assembler* assembler, int bits_per_entry) {
140  // Make sure the safepoint table is properly aligned. Pad with nops.
141  assembler->Align(kIntSize);
142  assembler->RecordComment(";;; Safepoint table.");
143  offset_ = assembler->pc_offset();
144 
145  // Take the register bits into account.
146  bits_per_entry += kNumSafepointRegisters;
147 
148  // Compute the number of bytes per safepoint entry.
149  int bytes_per_entry =
150  RoundUp(bits_per_entry, kBitsPerByte) >> kBitsPerByteLog2;
151 
152  // Emit the table header.
153  int length = deoptimization_info_.length();
154  assembler->dd(length);
155  assembler->dd(bytes_per_entry);
156 
157  // Emit sorted table of pc offsets together with deoptimization indexes.
158  for (int i = 0; i < length; i++) {
159  assembler->dd(deoptimization_info_[i].pc);
160  assembler->dd(EncodeExceptPC(deoptimization_info_[i],
161  deopt_index_list_[i]));
162  }
163 
164  // Emit table of bitmaps.
165  ZoneList<uint8_t> bits(bytes_per_entry, zone_);
166  for (int i = 0; i < length; i++) {
167  ZoneList<int>* indexes = indexes_[i];
168  ZoneList<int>* registers = registers_[i];
169  bits.Clear();
170  bits.AddBlock(0, bytes_per_entry, zone_);
171 
172  // Run through the registers (if any).
174  if (registers == NULL) {
175  const int num_reg_bytes = kNumSafepointRegisters >> kBitsPerByteLog2;
176  for (int j = 0; j < num_reg_bytes; j++) {
177  bits[j] = SafepointTable::kNoRegisters;
178  }
179  } else {
180  for (int j = 0; j < registers->length(); j++) {
181  int index = registers->at(j);
182  DCHECK(index >= 0 && index < kNumSafepointRegisters);
183  int byte_index = index >> kBitsPerByteLog2;
184  int bit_index = index & (kBitsPerByte - 1);
185  bits[byte_index] |= (1 << bit_index);
186  }
187  }
188 
189  // Run through the indexes and build a bitmap.
190  for (int j = 0; j < indexes->length(); j++) {
191  int index = bits_per_entry - 1 - indexes->at(j);
192  int byte_index = index >> kBitsPerByteLog2;
193  int bit_index = index & (kBitsPerByte - 1);
194  bits[byte_index] |= (1U << bit_index);
195  }
196 
197  // Emit the bitmap for the current entry.
198  for (int k = 0; k < bytes_per_entry; k++) {
199  assembler->db(bits[k]);
200  }
201  }
202  emitted_ = true;
203 }
204 
205 
206 uint32_t SafepointTableBuilder::EncodeExceptPC(const DeoptimizationInfo& info,
207  unsigned index) {
208  uint32_t encoding = SafepointEntry::DeoptimizationIndexField::encode(index);
209  encoding |= SafepointEntry::ArgumentsField::encode(info.arguments);
210  encoding |= SafepointEntry::SaveDoublesField::encode(info.has_doubles);
211  return encoding;
212 }
213 
214 
215 
216 } } // namespace v8::internal
virtual const char * NameOfCPURegister(int reg) const
static uint32_t & uint32_at(Address addr)
Definition: v8memory.h:24
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define DCHECK(condition)
Definition: logging.h:205
static uchar GetEntry(int32_t entry)
Definition: unicode.cc:33
const int kNumSafepointRegisters
Definition: frames-arm.h:67
const Register pc
const int kBitsPerByteLog2
Definition: globals.h:163
byte * Address
Definition: globals.h:101
const int kIntSize
Definition: globals.h:124
static void RoundUp(Vector< char > buffer, int *length, int *decimal_point)
Definition: fixed-dtoa.cc:171
STATIC_ASSERT(sizeof(CPURegister)==sizeof(Register))
const int kBitsPerByte
Definition: globals.h:162
bool IsAligned(T value, U alignment)
Definition: utils.h:123
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20