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