 Chromium Code Reviews
 Chromium Code Reviews Issue 1033273005:
  Layout descriptor must be trimmed when corresponding descriptors array is trimmed to stay in sync.  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master
    
  
    Issue 1033273005:
  Layout descriptor must be trimmed when corresponding descriptors array is trimmed to stay in sync.  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master| OLD | NEW | 
|---|---|
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include <sstream> | 5 #include <sstream> | 
| 6 | 6 | 
| 7 #include "src/v8.h" | 7 #include "src/v8.h" | 
| 8 | 8 | 
| 9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" | 
| 10 #include "src/layout-descriptor.h" | 10 #include "src/layout-descriptor.h" | 
| 11 | 11 | 
| 12 using v8::base::bits::CountTrailingZeros32; | 12 using v8::base::bits::CountTrailingZeros32; | 
| 13 | 13 | 
| 14 namespace v8 { | 14 namespace v8 { | 
| 15 namespace internal { | 15 namespace internal { | 
| 16 | 16 | 
| 17 Handle<LayoutDescriptor> LayoutDescriptor::New( | 17 Handle<LayoutDescriptor> LayoutDescriptor::New( | 
| 18 Handle<Map> map, Handle<DescriptorArray> descriptors, int num_descriptors) { | 18 Handle<Map> map, Handle<DescriptorArray> descriptors, int num_descriptors) { | 
| 19 Isolate* isolate = descriptors->GetIsolate(); | 19 Isolate* isolate = descriptors->GetIsolate(); | 
| 20 if (!FLAG_unbox_double_fields) return handle(FastPointerLayout(), isolate); | 20 if (!FLAG_unbox_double_fields) return handle(FastPointerLayout(), isolate); | 
| 21 | 21 | 
| 22 int inobject_properties = map->inobject_properties(); | 22 int layout_descriptor_length = | 
| 23 if (inobject_properties == 0) return handle(FastPointerLayout(), isolate); | 23 CalculateCapacity(*map, *descriptors, num_descriptors); | 
| 24 | 24 | 
| 25 DCHECK(num_descriptors <= descriptors->number_of_descriptors()); | 25 if (layout_descriptor_length == 0) { | 
| 26 | 26 // No double fields were found, use fast pointer layout. | 
| 27 int layout_descriptor_length; | 27 return handle(FastPointerLayout(), isolate); | 
| 28 const int kMaxWordsPerField = kDoubleSize / kPointerSize; | |
| 29 | |
| 30 if (num_descriptors <= kSmiValueSize / kMaxWordsPerField) { | |
| 31 // Even in the "worst" case (all fields are doubles) it would fit into | |
| 32 // a Smi, so no need to calculate length. | |
| 33 layout_descriptor_length = kSmiValueSize; | |
| 34 | |
| 35 } else { | |
| 36 layout_descriptor_length = 0; | |
| 37 | |
| 38 for (int i = 0; i < num_descriptors; i++) { | |
| 39 PropertyDetails details = descriptors->GetDetails(i); | |
| 40 if (!InobjectUnboxedField(inobject_properties, details)) continue; | |
| 41 int field_index = details.field_index(); | |
| 42 int field_width_in_words = details.field_width_in_words(); | |
| 43 layout_descriptor_length = | |
| 44 Max(layout_descriptor_length, field_index + field_width_in_words); | |
| 45 } | |
| 46 | |
| 47 if (layout_descriptor_length == 0) { | |
| 48 // No double fields were found, use fast pointer layout. | |
| 49 return handle(FastPointerLayout(), isolate); | |
| 50 } | |
| 51 } | 28 } | 
| 52 layout_descriptor_length = Min(layout_descriptor_length, inobject_properties); | |
| 53 | 29 | 
| 54 // Initially, layout descriptor corresponds to an object with all fields | 30 // Initially, layout descriptor corresponds to an object with all fields | 
| 55 // tagged. | 31 // tagged. | 
| 56 Handle<LayoutDescriptor> layout_descriptor_handle = | 32 Handle<LayoutDescriptor> layout_descriptor_handle = | 
| 57 LayoutDescriptor::New(isolate, layout_descriptor_length); | 33 LayoutDescriptor::New(isolate, layout_descriptor_length); | 
| 58 | 34 | 
| 59 DisallowHeapAllocation no_allocation; | 35 LayoutDescriptor* layout_descriptor = Initialize( | 
| 60 LayoutDescriptor* layout_descriptor = *layout_descriptor_handle; | 36 *layout_descriptor_handle, *map, *descriptors, num_descriptors); | 
| 61 | 37 | 
| 62 for (int i = 0; i < num_descriptors; i++) { | |
| 63 PropertyDetails details = descriptors->GetDetails(i); | |
| 64 if (!InobjectUnboxedField(inobject_properties, details)) continue; | |
| 65 int field_index = details.field_index(); | |
| 66 layout_descriptor = layout_descriptor->SetRawData(field_index); | |
| 67 if (details.field_width_in_words() > 1) { | |
| 68 layout_descriptor = layout_descriptor->SetRawData(field_index + 1); | |
| 69 } | |
| 70 } | |
| 71 return handle(layout_descriptor, isolate); | 38 return handle(layout_descriptor, isolate); | 
| 72 } | 39 } | 
| 73 | 40 | 
| 74 | 41 | 
| 75 Handle<LayoutDescriptor> LayoutDescriptor::ShareAppend( | 42 Handle<LayoutDescriptor> LayoutDescriptor::ShareAppend( | 
| 76 Handle<Map> map, PropertyDetails details) { | 43 Handle<Map> map, PropertyDetails details) { | 
| 77 DCHECK(map->owns_descriptors()); | 44 DCHECK(map->owns_descriptors()); | 
| 78 Isolate* isolate = map->GetIsolate(); | 45 Isolate* isolate = map->GetIsolate(); | 
| 79 Handle<LayoutDescriptor> layout_descriptor(map->GetLayoutDescriptor(), | 46 Handle<LayoutDescriptor> layout_descriptor(map->GetLayoutDescriptor(), | 
| 80 isolate); | 47 isolate); | 
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 251 DCHECK(offset_in_bytes < *out_end_of_contiguous_region_offset); | 218 DCHECK(offset_in_bytes < *out_end_of_contiguous_region_offset); | 
| 252 return true; | 219 return true; | 
| 253 } | 220 } | 
| 254 *out_end_of_contiguous_region_offset = | 221 *out_end_of_contiguous_region_offset = | 
| 255 offset_in_bytes + sequence_length * kPointerSize; | 222 offset_in_bytes + sequence_length * kPointerSize; | 
| 256 DCHECK(offset_in_bytes < *out_end_of_contiguous_region_offset); | 223 DCHECK(offset_in_bytes < *out_end_of_contiguous_region_offset); | 
| 257 return tagged; | 224 return tagged; | 
| 258 } | 225 } | 
| 259 | 226 | 
| 260 | 227 | 
| 261 bool LayoutDescriptor::IsConsistentWithMap(Map* map) { | 228 LayoutDescriptor* LayoutDescriptor::Trim(Heap* heap, Map* map, | 
| 229 DescriptorArray* descriptors, | |
| 230 int num_descriptors) { | |
| 231 DisallowHeapAllocation no_allocation; | |
| 232 // Fast mode descriptors are never shared and therefore always fully | |
| 233 // correspond to their map. | |
| 234 if (!IsSlowLayout()) return this; | |
| 235 | |
| 236 int layout_descriptor_length = | |
| 237 CalculateCapacity(map, descriptors, num_descriptors); | |
| 238 // It must not become fast-mode descriptor here, because otherwise it has to | |
| 239 // be fast pointer layout descriptor already but it's is slow mode now. | |
| 240 DCHECK_LT(kSmiValueSize, layout_descriptor_length); | |
| 241 | |
| 242 // Trim, clean and reinitialize this slow-mode layout descriptor. | |
| 243 int array_length = GetSlowModeBackingStoreLength(layout_descriptor_length); | |
| 244 int current_length = length(); | |
| 245 if (current_length != array_length) { | |
| 246 DCHECK_LT(array_length, current_length); | |
| 247 int delta = current_length - array_length; | |
| 248 heap->RightTrimFixedArray<Heap::FROM_GC>(this, delta); | |
| 
Toon Verwaest
2015/03/30 16:10:21
I hope DataSize() is updated here? Otherwise you'l
 
Igor Sheludko
2015/03/30 16:33:27
Yes, sure! It's length() * elements_size, essentia
 | |
| 249 } | |
| 250 memset(DataPtr(), 0, DataSize()); | |
| 251 LayoutDescriptor* layout_descriptor = | |
| 252 Initialize(this, map, descriptors, num_descriptors); | |
| 253 DCHECK_EQ(this, layout_descriptor); | |
| 254 return layout_descriptor; | |
| 255 } | |
| 256 | |
| 257 | |
| 258 bool LayoutDescriptor::IsConsistentWithMap(Map* map, bool check_tail) { | |
| 262 if (FLAG_unbox_double_fields) { | 259 if (FLAG_unbox_double_fields) { | 
| 263 DescriptorArray* descriptors = map->instance_descriptors(); | 260 DescriptorArray* descriptors = map->instance_descriptors(); | 
| 264 int nof_descriptors = map->NumberOfOwnDescriptors(); | 261 int nof_descriptors = map->NumberOfOwnDescriptors(); | 
| 262 int last_field_index = 0; | |
| 265 for (int i = 0; i < nof_descriptors; i++) { | 263 for (int i = 0; i < nof_descriptors; i++) { | 
| 266 PropertyDetails details = descriptors->GetDetails(i); | 264 PropertyDetails details = descriptors->GetDetails(i); | 
| 267 if (details.type() != DATA) continue; | 265 if (details.location() != kField) continue; | 
| 268 FieldIndex field_index = FieldIndex::ForDescriptor(map, i); | 266 FieldIndex field_index = FieldIndex::ForDescriptor(map, i); | 
| 269 bool tagged_expected = | 267 bool tagged_expected = | 
| 270 !field_index.is_inobject() || !details.representation().IsDouble(); | 268 !field_index.is_inobject() || !details.representation().IsDouble(); | 
| 271 for (int bit = 0; bit < details.field_width_in_words(); bit++) { | 269 for (int bit = 0; bit < details.field_width_in_words(); bit++) { | 
| 272 bool tagged_actual = IsTagged(details.field_index() + bit); | 270 bool tagged_actual = IsTagged(details.field_index() + bit); | 
| 273 DCHECK_EQ(tagged_expected, tagged_actual); | 271 DCHECK_EQ(tagged_expected, tagged_actual); | 
| 274 if (tagged_actual != tagged_expected) return false; | 272 if (tagged_actual != tagged_expected) return false; | 
| 275 } | 273 } | 
| 274 last_field_index = | |
| 275 Max(last_field_index, | |
| 276 details.field_index() + details.field_width_in_words()); | |
| 277 } | |
| 278 if (check_tail) { | |
| 279 int n = capacity(); | |
| 280 for (int i = last_field_index; i < n; i++) { | |
| 281 DCHECK(IsTagged(i)); | |
| 282 } | |
| 276 } | 283 } | 
| 277 } | 284 } | 
| 278 return true; | 285 return true; | 
| 279 } | 286 } | 
| 280 } | 287 } | 
| 281 } // namespace v8::internal | 288 } // namespace v8::internal | 
| OLD | NEW |