ceee09a8105603102d201b8d812cc7f0ec194325
[platform/upstream/nodejs.git] / deps / v8 / src / 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 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   if (length <= kSmiValueSize) {
20     // The whole bit vector fits into a smi.
21     return handle(LayoutDescriptor::FromSmi(Smi::FromInt(0)), isolate);
22   }
23
24   length = (length + kNumberOfBits - 1) / kNumberOfBits;
25   DCHECK(length > 0);
26
27   if (SmiValuesAre32Bits() && (length & 1)) {
28     // On 64-bit systems if the length is odd then the half-word space would be
29     // lost anyway (due to alignment and the fact that we are allocating
30     // uint32-typed array), so we increase the length of allocated array
31     // to utilize that "lost" space which could also help to avoid layout
32     // descriptor reallocations.
33     ++length;
34   }
35   return Handle<LayoutDescriptor>::cast(
36       isolate->factory()->NewFixedTypedArray(length, kExternalUint32Array));
37 }
38
39
40 bool LayoutDescriptor::InobjectUnboxedField(int inobject_properties,
41                                             PropertyDetails details) {
42   if (details.type() != DATA || !details.representation().IsDouble()) {
43     return false;
44   }
45   // We care only about in-object properties.
46   return details.field_index() < inobject_properties;
47 }
48
49
50 LayoutDescriptor* LayoutDescriptor::FastPointerLayout() {
51   return LayoutDescriptor::FromSmi(Smi::FromInt(0));
52 }
53
54
55 bool LayoutDescriptor::GetIndexes(int field_index, int* layout_word_index,
56                                   int* layout_bit_index) {
57   if (static_cast<unsigned>(field_index) >= static_cast<unsigned>(capacity())) {
58     return false;
59   }
60
61   *layout_word_index = field_index / kNumberOfBits;
62   CHECK((!IsSmi() && (*layout_word_index < length())) ||
63         (IsSmi() && (*layout_word_index < 1)));
64
65   *layout_bit_index = field_index % kNumberOfBits;
66   return true;
67 }
68
69
70 LayoutDescriptor* LayoutDescriptor::SetTagged(int field_index, bool tagged) {
71   int layout_word_index;
72   int layout_bit_index;
73
74   if (!GetIndexes(field_index, &layout_word_index, &layout_bit_index)) {
75     CHECK(false);
76     return this;
77   }
78   uint32_t layout_mask = static_cast<uint32_t>(1) << layout_bit_index;
79
80   if (IsSlowLayout()) {
81     uint32_t value = get_scalar(layout_word_index);
82     if (tagged) {
83       value &= ~layout_mask;
84     } else {
85       value |= layout_mask;
86     }
87     set(layout_word_index, value);
88     return this;
89   } else {
90     uint32_t value = static_cast<uint32_t>(Smi::cast(this)->value());
91     if (tagged) {
92       value &= ~layout_mask;
93     } else {
94       value |= layout_mask;
95     }
96     return LayoutDescriptor::FromSmi(Smi::FromInt(static_cast<int>(value)));
97   }
98 }
99
100
101 bool LayoutDescriptor::IsTagged(int field_index) {
102   if (IsFastPointerLayout()) return true;
103
104   int layout_word_index;
105   int layout_bit_index;
106
107   if (!GetIndexes(field_index, &layout_word_index, &layout_bit_index)) {
108     // All bits after Out of bounds queries
109     return true;
110   }
111   uint32_t layout_mask = static_cast<uint32_t>(1) << layout_bit_index;
112
113   if (IsSlowLayout()) {
114     uint32_t value = get_scalar(layout_word_index);
115     return (value & layout_mask) == 0;
116   } else {
117     uint32_t value = static_cast<uint32_t>(Smi::cast(this)->value());
118     return (value & layout_mask) == 0;
119   }
120 }
121
122
123 bool LayoutDescriptor::IsFastPointerLayout() {
124   return this == FastPointerLayout();
125 }
126
127
128 bool LayoutDescriptor::IsFastPointerLayout(Object* layout_descriptor) {
129   return layout_descriptor == FastPointerLayout();
130 }
131
132
133 bool LayoutDescriptor::IsSlowLayout() { return !IsSmi(); }
134
135
136 int LayoutDescriptor::capacity() {
137   return IsSlowLayout() ? (length() * kNumberOfBits) : kSmiValueSize;
138 }
139
140
141 LayoutDescriptor* LayoutDescriptor::cast_gc_safe(Object* object) {
142   if (object->IsSmi()) {
143     // Fast mode layout descriptor.
144     return reinterpret_cast<LayoutDescriptor*>(object);
145   }
146
147   // This is a mixed descriptor which is a fixed typed array.
148   MapWord map_word = reinterpret_cast<HeapObject*>(object)->map_word();
149   if (map_word.IsForwardingAddress()) {
150     // Mark-compact has already moved layout descriptor.
151     object = map_word.ToForwardingAddress();
152   }
153   return LayoutDescriptor::cast(object);
154 }
155
156
157 // InobjectPropertiesHelper is a helper class for querying whether inobject
158 // property at offset is Double or not.
159 LayoutDescriptorHelper::LayoutDescriptorHelper(Map* map)
160     : all_fields_tagged_(true),
161       header_size_(0),
162       layout_descriptor_(LayoutDescriptor::FastPointerLayout()) {
163   if (!FLAG_unbox_double_fields) return;
164
165   layout_descriptor_ = map->layout_descriptor_gc_safe();
166   if (layout_descriptor_->IsFastPointerLayout()) {
167     return;
168   }
169
170   int inobject_properties = map->inobject_properties();
171   DCHECK(inobject_properties > 0);
172   header_size_ = map->instance_size() - (inobject_properties * kPointerSize);
173   DCHECK(header_size_ >= 0);
174
175   all_fields_tagged_ = false;
176 }
177
178
179 bool LayoutDescriptorHelper::IsTagged(int offset_in_bytes) {
180   DCHECK(IsAligned(offset_in_bytes, kPointerSize));
181   if (all_fields_tagged_) return true;
182   // Object headers do not contain non-tagged fields.
183   if (offset_in_bytes < header_size_) return true;
184   int field_index = (offset_in_bytes - header_size_) / kPointerSize;
185
186   return layout_descriptor_->IsTagged(field_index);
187 }
188 }
189 }  // namespace v8::internal
190
191 #endif  // V8_LAYOUT_DESCRIPTOR_INL_H_