V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
layout-descriptor-inl.h
1 // Copyright 2014 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 #ifndef V8_LAYOUT_DESCRIPTOR_INL_H_
6 #define V8_LAYOUT_DESCRIPTOR_INL_H_
7 
8 #include "src/layout-descriptor.h"
9 
10 #include "src/objects-inl.h"
11 #include "src/objects/descriptor-array.h"
12 #include "src/objects/smi.h"
13 
14 // Has to be the last include (doesn't have include guards):
15 #include "src/objects/object-macros.h"
16 
17 namespace v8 {
18 namespace internal {
19 
20 LayoutDescriptor::LayoutDescriptor(Address ptr)
21  : ByteArray(ptr, AllowInlineSmiStorage::kAllowBeingASmi) {
22  SLOW_DCHECK(IsLayoutDescriptor());
23 }
24 CAST_ACCESSOR2(LayoutDescriptor)
25 
26 LayoutDescriptor LayoutDescriptor::FromSmi(Smi smi) {
27  return LayoutDescriptor::cast(smi);
28 }
29 
30 Handle<LayoutDescriptor> LayoutDescriptor::New(Isolate* isolate, int length) {
31  if (length <= kBitsInSmiLayout) {
32  // The whole bit vector fits into a smi.
33  return handle(LayoutDescriptor::FromSmi(Smi::zero()), isolate);
34  }
35  int backing_store_length = GetSlowModeBackingStoreLength(length);
36  Handle<LayoutDescriptor> result = Handle<LayoutDescriptor>::cast(
37  isolate->factory()->NewByteArray(backing_store_length, TENURED));
38  memset(reinterpret_cast<void*>(result->GetDataStartAddress()), 0,
39  result->DataSize());
40  return result;
41 }
42 
43 
44 bool LayoutDescriptor::InobjectUnboxedField(int inobject_properties,
45  PropertyDetails details) {
46  if (details.location() != kField || !details.representation().IsDouble()) {
47  return false;
48  }
49  // We care only about in-object properties.
50  return details.field_index() < inobject_properties;
51 }
52 
53 LayoutDescriptor LayoutDescriptor::FastPointerLayout() {
54  return LayoutDescriptor::FromSmi(Smi::zero());
55 }
56 
57 bool LayoutDescriptor::GetIndexes(int field_index, int* layout_word_index,
58  int* layout_bit_index) {
59  if (static_cast<unsigned>(field_index) >= static_cast<unsigned>(capacity())) {
60  return false;
61  }
62 
63  *layout_word_index = field_index / kBitsPerLayoutWord;
64  CHECK((!IsSmi() && (*layout_word_index < length())) ||
65  (IsSmi() && (*layout_word_index < 1)));
66 
67  *layout_bit_index = field_index % kBitsPerLayoutWord;
68  return true;
69 }
70 
71 LayoutDescriptor LayoutDescriptor::SetRawData(int field_index) {
72  return SetTagged(field_index, false);
73 }
74 
75 LayoutDescriptor LayoutDescriptor::SetTagged(int field_index, bool tagged) {
76  int layout_word_index = 0;
77  int layout_bit_index = 0;
78 
79  CHECK(GetIndexes(field_index, &layout_word_index, &layout_bit_index));
80  uint32_t layout_mask = static_cast<uint32_t>(1) << layout_bit_index;
81 
82  if (IsSlowLayout()) {
83  uint32_t value = get_layout_word(layout_word_index);
84  if (tagged) {
85  value &= ~layout_mask;
86  } else {
87  value |= layout_mask;
88  }
89  set_layout_word(layout_word_index, value);
90  return *this;
91  } else {
92  uint32_t value = static_cast<uint32_t>(Smi::ToInt(*this));
93  if (tagged) {
94  value &= ~layout_mask;
95  } else {
96  value |= layout_mask;
97  }
98  return LayoutDescriptor::FromSmi(Smi::FromInt(static_cast<int>(value)));
99  }
100 }
101 
102 bool LayoutDescriptor::IsTagged(int field_index) {
103  if (IsFastPointerLayout()) return true;
104 
105  int layout_word_index;
106  int layout_bit_index;
107 
108  if (!GetIndexes(field_index, &layout_word_index, &layout_bit_index)) {
109  // All bits after Out of bounds queries
110  return true;
111  }
112  uint32_t layout_mask = static_cast<uint32_t>(1) << layout_bit_index;
113 
114  if (IsSlowLayout()) {
115  uint32_t value = get_layout_word(layout_word_index);
116  return (value & layout_mask) == 0;
117  } else {
118  uint32_t value = static_cast<uint32_t>(Smi::ToInt(*this));
119  return (value & layout_mask) == 0;
120  }
121 }
122 
123 
124 bool LayoutDescriptor::IsFastPointerLayout() {
125  return *this == FastPointerLayout();
126 }
127 
128 
129 bool LayoutDescriptor::IsFastPointerLayout(Object* layout_descriptor) {
130  return layout_descriptor == FastPointerLayout();
131 }
132 
133 
134 bool LayoutDescriptor::IsSlowLayout() { return !IsSmi(); }
135 
136 
137 int LayoutDescriptor::capacity() {
138  return IsSlowLayout() ? (length() * kBitsPerByte) : kBitsInSmiLayout;
139 }
140 
141 LayoutDescriptor LayoutDescriptor::cast_gc_safe(Object* object) {
142  // The map word of the object can be a forwarding pointer during
143  // object evacuation phase of GC. Since the layout descriptor methods
144  // for checking whether a field is tagged or not do not depend on the
145  // object map, it should be safe.
146  return LayoutDescriptor::unchecked_cast(object);
147 }
148 
149 int LayoutDescriptor::GetSlowModeBackingStoreLength(int length) {
150  DCHECK_LT(0, length);
151  // We allocate kPointerSize rounded blocks of memory anyway so we increase
152  // the length of allocated array to utilize that "lost" space which could
153  // also help to avoid layout descriptor reallocations.
154  return RoundUp(length, kBitsPerByte * kPointerSize) / kBitsPerByte;
155 }
156 
157 int LayoutDescriptor::CalculateCapacity(Map map, DescriptorArray* descriptors,
158  int num_descriptors) {
159  int inobject_properties = map->GetInObjectProperties();
160  if (inobject_properties == 0) return 0;
161 
162  DCHECK_LE(num_descriptors, descriptors->number_of_descriptors());
163 
164  int layout_descriptor_length;
165  const int kMaxWordsPerField = kDoubleSize / kPointerSize;
166 
167  if (num_descriptors <= kBitsInSmiLayout / kMaxWordsPerField) {
168  // Even in the "worst" case (all fields are doubles) it would fit into
169  // a Smi, so no need to calculate length.
170  layout_descriptor_length = kBitsInSmiLayout;
171 
172  } else {
173  layout_descriptor_length = 0;
174 
175  for (int i = 0; i < num_descriptors; i++) {
176  PropertyDetails details = descriptors->GetDetails(i);
177  if (!InobjectUnboxedField(inobject_properties, details)) continue;
178  int field_index = details.field_index();
179  int field_width_in_words = details.field_width_in_words();
180  layout_descriptor_length =
181  Max(layout_descriptor_length, field_index + field_width_in_words);
182  }
183  }
184  layout_descriptor_length = Min(layout_descriptor_length, inobject_properties);
185  return layout_descriptor_length;
186 }
187 
188 LayoutDescriptor LayoutDescriptor::Initialize(
189  LayoutDescriptor layout_descriptor, Map map, DescriptorArray* descriptors,
190  int num_descriptors) {
191  DisallowHeapAllocation no_allocation;
192  int inobject_properties = map->GetInObjectProperties();
193 
194  for (int i = 0; i < num_descriptors; i++) {
195  PropertyDetails details = descriptors->GetDetails(i);
196  if (!InobjectUnboxedField(inobject_properties, details)) {
197  DCHECK(details.location() != kField ||
198  layout_descriptor->IsTagged(details.field_index()));
199  continue;
200  }
201  int field_index = details.field_index();
202  layout_descriptor = layout_descriptor->SetRawData(field_index);
203  if (details.field_width_in_words() > 1) {
204  layout_descriptor = layout_descriptor->SetRawData(field_index + 1);
205  }
206  }
207  return layout_descriptor;
208 }
209 
210 int LayoutDescriptor::number_of_layout_words() {
211  return length() / kUInt32Size;
212 }
213 
214 uint32_t LayoutDescriptor::get_layout_word(int index) const {
215  return get_uint32(index);
216 }
217 
218 void LayoutDescriptor::set_layout_word(int index, uint32_t value) {
219  set_uint32(index, value);
220 }
221 
222 // LayoutDescriptorHelper is a helper class for querying whether inobject
223 // property at offset is Double or not.
224 LayoutDescriptorHelper::LayoutDescriptorHelper(Map map)
225  : all_fields_tagged_(true),
226  header_size_(0),
227  layout_descriptor_(LayoutDescriptor::FastPointerLayout()) {
228  if (!FLAG_unbox_double_fields) return;
229 
230  layout_descriptor_ = map->layout_descriptor_gc_safe();
231  if (layout_descriptor_->IsFastPointerLayout()) {
232  return;
233  }
234 
235  header_size_ = map->GetInObjectPropertiesStartInWords() * kPointerSize;
236  DCHECK_GE(header_size_, 0);
237 
238  all_fields_tagged_ = false;
239 }
240 
241 
242 bool LayoutDescriptorHelper::IsTagged(int offset_in_bytes) {
243  DCHECK(IsAligned(offset_in_bytes, kPointerSize));
244  if (all_fields_tagged_) return true;
245  // Object headers do not contain non-tagged fields.
246  if (offset_in_bytes < header_size_) return true;
247  int field_index = (offset_in_bytes - header_size_) / kPointerSize;
248 
249  return layout_descriptor_->IsTagged(field_index);
250 }
251 
252 } // namespace internal
253 } // namespace v8
254 
255 #include "src/objects/object-macros-undef.h"
256 
257 #endif // V8_LAYOUT_DESCRIPTOR_INL_H_
Definition: libplatform.h:13