5 #include "src/layout-descriptor.h" 9 #include "src/base/bits.h" 10 #include "src/handles-inl.h" 11 #include "src/objects-inl.h" 16 Handle<LayoutDescriptor> LayoutDescriptor::New(
17 Isolate* isolate, Handle<Map> map, Handle<DescriptorArray> descriptors,
18 int num_descriptors) {
19 if (!FLAG_unbox_double_fields)
return handle(FastPointerLayout(), isolate);
21 int layout_descriptor_length =
22 CalculateCapacity(*map, *descriptors, num_descriptors);
24 if (layout_descriptor_length == 0) {
26 return handle(FastPointerLayout(), isolate);
31 Handle<LayoutDescriptor> layout_descriptor_handle =
32 LayoutDescriptor::New(isolate, layout_descriptor_length);
34 LayoutDescriptor layout_descriptor = Initialize(
35 *layout_descriptor_handle, *map, *descriptors, num_descriptors);
37 return handle(layout_descriptor, isolate);
40 Handle<LayoutDescriptor> LayoutDescriptor::ShareAppend(
41 Isolate* isolate, Handle<Map> map, PropertyDetails details) {
42 DCHECK(map->owns_descriptors());
43 Handle<LayoutDescriptor> layout_descriptor(map->GetLayoutDescriptor(),
46 if (!InobjectUnboxedField(map->GetInObjectProperties(), details)) {
47 DCHECK(details.location() != kField ||
48 layout_descriptor->IsTagged(details.field_index()));
49 return layout_descriptor;
51 int field_index = details.field_index();
52 layout_descriptor = LayoutDescriptor::EnsureCapacity(
53 isolate, layout_descriptor, field_index + details.field_width_in_words());
55 DisallowHeapAllocation no_allocation;
56 LayoutDescriptor layout_desc = *layout_descriptor;
57 layout_desc = layout_desc->SetRawData(field_index);
58 if (details.field_width_in_words() > 1) {
59 layout_desc = layout_desc->SetRawData(field_index + 1);
61 return handle(layout_desc, isolate);
64 Handle<LayoutDescriptor> LayoutDescriptor::AppendIfFastOrUseFull(
65 Isolate* isolate, Handle<Map> map, PropertyDetails details,
66 Handle<LayoutDescriptor> full_layout_descriptor) {
67 DisallowHeapAllocation no_allocation;
68 LayoutDescriptor layout_descriptor = map->layout_descriptor();
69 if (layout_descriptor->IsSlowLayout()) {
70 return full_layout_descriptor;
72 if (!InobjectUnboxedField(map->GetInObjectProperties(), details)) {
73 DCHECK(details.location() != kField ||
74 layout_descriptor->IsTagged(details.field_index()));
75 return handle(layout_descriptor, isolate);
77 int field_index = details.field_index();
78 int new_capacity = field_index + details.field_width_in_words();
79 if (new_capacity > layout_descriptor->capacity()) {
82 return full_layout_descriptor;
85 layout_descriptor = layout_descriptor->SetRawData(field_index);
86 if (details.field_width_in_words() > 1) {
87 layout_descriptor = layout_descriptor->SetRawData(field_index + 1);
89 return handle(layout_descriptor, isolate);
93 Handle<LayoutDescriptor> LayoutDescriptor::EnsureCapacity(
94 Isolate* isolate, Handle<LayoutDescriptor> layout_descriptor,
96 int old_capacity = layout_descriptor->capacity();
97 if (new_capacity <= old_capacity) {
98 return layout_descriptor;
100 Handle<LayoutDescriptor> new_layout_descriptor =
101 LayoutDescriptor::New(isolate, new_capacity);
102 DCHECK(new_layout_descriptor->IsSlowLayout());
104 if (layout_descriptor->IsSlowLayout()) {
105 memcpy(new_layout_descriptor->GetDataStartAddress(),
106 layout_descriptor->GetDataStartAddress(),
107 layout_descriptor->DataSize());
108 return new_layout_descriptor;
112 new_layout_descriptor->set_layout_word(0, value);
113 return new_layout_descriptor;
118 bool LayoutDescriptor::IsTagged(
int field_index,
int max_sequence_length,
119 int* out_sequence_length) {
120 DCHECK_GT(max_sequence_length, 0);
121 if (IsFastPointerLayout()) {
122 *out_sequence_length = max_sequence_length;
126 int layout_word_index;
127 int layout_bit_index;
129 if (!GetIndexes(field_index, &layout_word_index, &layout_bit_index)) {
131 *out_sequence_length = max_sequence_length;
136 uint32_t value = IsSlowLayout() ? get_layout_word(layout_word_index)
137 : static_cast<
uint32_t>(Smi::ToInt(*this));
139 bool is_tagged = (value & layout_mask) == 0;
140 if (!is_tagged) value = ~value;
141 value = value & ~(layout_mask - 1);
143 if (IsSlowLayout()) {
144 sequence_length = base::bits::CountTrailingZeros(value) - layout_bit_index;
146 if (layout_bit_index + sequence_length == kBitsPerLayoutWord) {
150 int num_words = number_of_layout_words();
151 for (; layout_word_index < num_words; layout_word_index++) {
152 value = get_layout_word(layout_word_index);
153 bool cur_is_tagged = (value & 1) == 0;
154 if (cur_is_tagged != is_tagged)
break;
155 if (!is_tagged) value = ~value;
156 int cur_sequence_length = base::bits::CountTrailingZeros(value);
157 sequence_length += cur_sequence_length;
158 if (sequence_length >= max_sequence_length)
break;
159 if (cur_sequence_length != kBitsPerLayoutWord)
break;
161 if (is_tagged && (field_index + sequence_length == capacity())) {
165 sequence_length = std::numeric_limits<int>::max();
169 sequence_length = Min(base::bits::CountTrailingZeros(value),
170 static_cast<unsigned>(kBitsInSmiLayout)) -
172 if (is_tagged && (field_index + sequence_length == capacity())) {
176 sequence_length = std::numeric_limits<int>::max();
179 *out_sequence_length = Min(sequence_length, max_sequence_length);
184 Handle<LayoutDescriptor> LayoutDescriptor::NewForTesting(Isolate* isolate,
186 return New(isolate, length);
189 LayoutDescriptor LayoutDescriptor::SetTaggedForTesting(
int field_index,
191 return SetTagged(field_index, tagged);
194 bool LayoutDescriptorHelper::IsTagged(
195 int offset_in_bytes,
int end_offset,
196 int* out_end_of_contiguous_region_offset) {
197 DCHECK(IsAligned(offset_in_bytes, kPointerSize));
198 DCHECK(IsAligned(end_offset, kPointerSize));
199 DCHECK(offset_in_bytes < end_offset);
200 if (all_fields_tagged_) {
201 *out_end_of_contiguous_region_offset = end_offset;
202 DCHECK(offset_in_bytes < *out_end_of_contiguous_region_offset);
205 int max_sequence_length = (end_offset - offset_in_bytes) / kPointerSize;
206 int field_index = Max(0, (offset_in_bytes - header_size_) / kPointerSize);
208 bool tagged = layout_descriptor_->IsTagged(field_index, max_sequence_length,
210 DCHECK_GT(sequence_length, 0);
211 if (offset_in_bytes < header_size_) {
216 *out_end_of_contiguous_region_offset =
217 header_size_ + sequence_length * kPointerSize;
220 *out_end_of_contiguous_region_offset = header_size_;
222 DCHECK(offset_in_bytes < *out_end_of_contiguous_region_offset);
225 *out_end_of_contiguous_region_offset =
226 offset_in_bytes + sequence_length * kPointerSize;
227 DCHECK(offset_in_bytes < *out_end_of_contiguous_region_offset);
231 LayoutDescriptor LayoutDescriptor::Trim(Heap* heap, Map map,
232 DescriptorArray* descriptors,
233 int num_descriptors) {
234 DisallowHeapAllocation no_allocation;
237 if (!IsSlowLayout())
return *
this;
239 int layout_descriptor_length =
240 CalculateCapacity(map, descriptors, num_descriptors);
243 DCHECK_LT(kBitsInSmiLayout, layout_descriptor_length);
246 int new_backing_store_length =
247 GetSlowModeBackingStoreLength(layout_descriptor_length);
248 int backing_store_length = length();
249 if (new_backing_store_length != backing_store_length) {
250 DCHECK_LT(new_backing_store_length, backing_store_length);
251 int delta = backing_store_length - new_backing_store_length;
252 heap->RightTrimFixedArray(*
this, delta);
254 memset(GetDataStartAddress(), 0, DataSize());
255 LayoutDescriptor layout_descriptor =
256 Initialize(*
this, map, descriptors, num_descriptors);
257 DCHECK_EQ(*
this, layout_descriptor);
258 return layout_descriptor;
261 bool LayoutDescriptor::IsConsistentWithMap(Map map,
bool check_tail) {
262 if (FLAG_unbox_double_fields) {
263 DescriptorArray* descriptors = map->instance_descriptors();
264 int nof_descriptors = map->NumberOfOwnDescriptors();
265 int last_field_index = 0;
266 for (
int i = 0;
i < nof_descriptors;
i++) {
267 PropertyDetails details = descriptors->GetDetails(
i);
268 if (details.location() != kField)
continue;
269 FieldIndex field_index = FieldIndex::ForDescriptor(map,
i);
270 bool tagged_expected =
271 !field_index.is_inobject() || !details.representation().IsDouble();
272 for (
int bit = 0; bit < details.field_width_in_words(); bit++) {
273 bool tagged_actual = IsTagged(details.field_index() + bit);
274 DCHECK_EQ(tagged_expected, tagged_actual);
275 if (tagged_actual != tagged_expected)
return false;
278 Max(last_field_index,
279 details.field_index() + details.field_width_in_words());
283 for (
int i = last_field_index;
i < n;
i++) {