OLD | NEW |
| (Empty) |
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() != FIELD || !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 uint32_t* layout_mask) { | |
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 int layout_bit_index = field_index % kNumberOfBits; | |
66 *layout_mask = static_cast<uint32_t>(1) << layout_bit_index; | |
67 return true; | |
68 } | |
69 | |
70 | |
71 LayoutDescriptor* LayoutDescriptor::SetTagged(int field_index, bool tagged) { | |
72 int layout_word_index; | |
73 uint32_t layout_mask; | |
74 | |
75 if (!GetIndexes(field_index, &layout_word_index, &layout_mask)) { | |
76 CHECK(false); | |
77 return this; | |
78 } | |
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 uint32_t layout_mask; | |
106 | |
107 if (!GetIndexes(field_index, &layout_word_index, &layout_mask)) { | |
108 // All bits after Out of bounds queries | |
109 return true; | |
110 } | |
111 | |
112 if (IsSlowLayout()) { | |
113 uint32_t value = get_scalar(layout_word_index); | |
114 return (value & layout_mask) == 0; | |
115 } else { | |
116 uint32_t value = static_cast<uint32_t>(Smi::cast(this)->value()); | |
117 return (value & layout_mask) == 0; | |
118 } | |
119 } | |
120 | |
121 | |
122 bool LayoutDescriptor::IsFastPointerLayout() { | |
123 return IsSmi() && (Smi::cast(this)->value() == 0); | |
124 } | |
125 | |
126 | |
127 bool LayoutDescriptor::IsSlowLayout() { return !IsSmi(); } | |
128 | |
129 | |
130 int LayoutDescriptor::capacity() { | |
131 return IsSlowLayout() ? (length() * kNumberOfBits) : kSmiValueSize; | |
132 } | |
133 | |
134 | |
135 LayoutDescriptor* LayoutDescriptor::cast_gc_safe(Object* object) { | |
136 if (object->IsSmi()) { | |
137 // Fast mode layout descriptor. | |
138 return reinterpret_cast<LayoutDescriptor*>(object); | |
139 } | |
140 | |
141 // This is a mixed descriptor which is a fixed typed array. | |
142 MapWord map_word = reinterpret_cast<HeapObject*>(object)->map_word(); | |
143 if (map_word.IsForwardingAddress()) { | |
144 // Mark-compact has already moved layout descriptor. | |
145 object = map_word.ToForwardingAddress(); | |
146 } | |
147 return LayoutDescriptor::cast(object); | |
148 } | |
149 | |
150 | |
151 // InobjectPropertiesHelper is a helper class for querying whether inobject | |
152 // property at offset is Double or not. | |
153 InobjectPropertiesHelper::InobjectPropertiesHelper(Map* map) | |
154 : all_fields_tagged_(true), | |
155 header_size_(0), | |
156 layout_descriptor_(LayoutDescriptor::FastPointerLayout()) { | |
157 if (!FLAG_unbox_double_fields) return; | |
158 | |
159 layout_descriptor_ = map->layout_descriptor_gc_safe(); | |
160 if (layout_descriptor_->IsFastPointerLayout()) { | |
161 return; | |
162 } | |
163 | |
164 int inobject_properties = map->inobject_properties(); | |
165 DCHECK(inobject_properties > 0); | |
166 header_size_ = map->instance_size() - (inobject_properties * kPointerSize); | |
167 DCHECK(header_size_ >= 0); | |
168 | |
169 all_fields_tagged_ = false; | |
170 } | |
171 | |
172 | |
173 bool InobjectPropertiesHelper::IsTagged(int offset_in_bytes) { | |
174 DCHECK(IsAligned(offset_in_bytes, kPointerSize)); | |
175 if (all_fields_tagged_) return true; | |
176 // Object headers do not contain non-tagged fields. | |
177 if (offset_in_bytes < header_size_) return true; | |
178 int field_index = (offset_in_bytes - header_size_) / kPointerSize; | |
179 | |
180 return layout_descriptor_->IsTagged(field_index); | |
181 } | |
182 } | |
183 } // namespace v8::internal | |
184 | |
185 #endif // V8_LAYOUT_DESCRIPTOR_INL_H_ | |
OLD | NEW |