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 #include <sstream> |
| 6 |
| 7 #include "src/v8.h" |
| 8 |
| 9 #include "src/layout-descriptor.h" |
| 10 |
| 11 namespace v8 { |
| 12 namespace internal { |
| 13 |
| 14 Handle<LayoutDescriptor> LayoutDescriptor::New( |
| 15 Handle<Map> map, Handle<DescriptorArray> descriptors, int num_descriptors) { |
| 16 Isolate* isolate = descriptors->GetIsolate(); |
| 17 if (!FLAG_unbox_double_fields) return handle(FastPointerLayout(), isolate); |
| 18 |
| 19 int inobject_properties = map->inobject_properties(); |
| 20 if (inobject_properties == 0) return handle(FastPointerLayout(), isolate); |
| 21 |
| 22 DCHECK(num_descriptors <= descriptors->number_of_descriptors()); |
| 23 |
| 24 int layout_descriptor_length; |
| 25 const int kMaxWordsPerField = kDoubleSize / kPointerSize; |
| 26 |
| 27 if (num_descriptors <= kSmiValueSize / kMaxWordsPerField) { |
| 28 // Even in the "worst" case (all fields are doubles) it would fit into |
| 29 // a Smi, so no need to calculate length. |
| 30 layout_descriptor_length = kSmiValueSize; |
| 31 |
| 32 } else { |
| 33 layout_descriptor_length = 0; |
| 34 |
| 35 for (int i = 0; i < num_descriptors; i++) { |
| 36 PropertyDetails details = descriptors->GetDetails(i); |
| 37 if (!InobjectUnboxedField(inobject_properties, details)) continue; |
| 38 int field_index = details.field_index(); |
| 39 int field_width_in_words = details.field_width_in_words(); |
| 40 layout_descriptor_length = |
| 41 Max(layout_descriptor_length, field_index + field_width_in_words); |
| 42 } |
| 43 |
| 44 if (layout_descriptor_length == 0) { |
| 45 // No double fields were found, use fast pointer layout. |
| 46 return handle(FastPointerLayout(), isolate); |
| 47 } |
| 48 } |
| 49 layout_descriptor_length = Min(layout_descriptor_length, inobject_properties); |
| 50 |
| 51 // Initially, layout descriptor corresponds to an object with all fields |
| 52 // tagged. |
| 53 Handle<LayoutDescriptor> layout_descriptor_handle = |
| 54 LayoutDescriptor::New(isolate, layout_descriptor_length); |
| 55 |
| 56 DisallowHeapAllocation no_allocation; |
| 57 LayoutDescriptor* layout_descriptor = *layout_descriptor_handle; |
| 58 |
| 59 for (int i = 0; i < num_descriptors; i++) { |
| 60 PropertyDetails details = descriptors->GetDetails(i); |
| 61 if (!InobjectUnboxedField(inobject_properties, details)) continue; |
| 62 int field_index = details.field_index(); |
| 63 layout_descriptor = layout_descriptor->SetRawData(field_index); |
| 64 if (details.field_width_in_words() > 1) { |
| 65 layout_descriptor = layout_descriptor->SetRawData(field_index + 1); |
| 66 } |
| 67 } |
| 68 return handle(layout_descriptor, isolate); |
| 69 } |
| 70 |
| 71 |
| 72 Handle<LayoutDescriptor> LayoutDescriptor::Append(Handle<Map> map, |
| 73 PropertyDetails details) { |
| 74 Isolate* isolate = map->GetIsolate(); |
| 75 Handle<LayoutDescriptor> layout_descriptor(map->GetLayoutDescriptor(), |
| 76 isolate); |
| 77 |
| 78 if (!InobjectUnboxedField(map->inobject_properties(), details)) { |
| 79 return layout_descriptor; |
| 80 } |
| 81 int field_index = details.field_index(); |
| 82 layout_descriptor = LayoutDescriptor::EnsureCapacity( |
| 83 isolate, layout_descriptor, field_index + details.field_width_in_words()); |
| 84 |
| 85 DisallowHeapAllocation no_allocation; |
| 86 LayoutDescriptor* layout_desc = *layout_descriptor; |
| 87 layout_desc = layout_desc->SetRawData(field_index); |
| 88 if (details.field_width_in_words() > 1) { |
| 89 layout_desc = layout_desc->SetRawData(field_index + 1); |
| 90 } |
| 91 return handle(layout_desc, isolate); |
| 92 } |
| 93 |
| 94 |
| 95 Handle<LayoutDescriptor> LayoutDescriptor::AppendIfFastOrUseFull( |
| 96 Handle<Map> map, PropertyDetails details, |
| 97 Handle<LayoutDescriptor> full_layout_descriptor) { |
| 98 DisallowHeapAllocation no_allocation; |
| 99 LayoutDescriptor* layout_descriptor = map->layout_descriptor(); |
| 100 if (layout_descriptor->IsSlowLayout()) { |
| 101 return full_layout_descriptor; |
| 102 } |
| 103 if (!InobjectUnboxedField(map->inobject_properties(), details)) { |
| 104 return handle(layout_descriptor, map->GetIsolate()); |
| 105 } |
| 106 int field_index = details.field_index(); |
| 107 int new_capacity = field_index + details.field_width_in_words(); |
| 108 if (new_capacity > layout_descriptor->capacity()) { |
| 109 // Current map's layout descriptor runs out of space, so use the full |
| 110 // layout descriptor. |
| 111 return full_layout_descriptor; |
| 112 } |
| 113 |
| 114 layout_descriptor = layout_descriptor->SetRawData(field_index); |
| 115 if (details.field_width_in_words() > 1) { |
| 116 layout_descriptor = layout_descriptor->SetRawData(field_index + 1); |
| 117 } |
| 118 return handle(layout_descriptor, map->GetIsolate()); |
| 119 } |
| 120 |
| 121 |
| 122 Handle<LayoutDescriptor> LayoutDescriptor::EnsureCapacity( |
| 123 Isolate* isolate, Handle<LayoutDescriptor> layout_descriptor, |
| 124 int new_capacity) { |
| 125 int old_capacity = layout_descriptor->capacity(); |
| 126 if (new_capacity <= old_capacity) { |
| 127 // Nothing to do with layout in Smi-form. |
| 128 return layout_descriptor; |
| 129 } |
| 130 Handle<LayoutDescriptor> new_layout_descriptor = |
| 131 LayoutDescriptor::New(isolate, new_capacity); |
| 132 DCHECK(new_layout_descriptor->IsSlowLayout()); |
| 133 |
| 134 if (layout_descriptor->IsSlowLayout()) { |
| 135 memcpy(new_layout_descriptor->DataPtr(), layout_descriptor->DataPtr(), |
| 136 layout_descriptor->DataSize()); |
| 137 return new_layout_descriptor; |
| 138 } else { |
| 139 // Fast layout. |
| 140 uint32_t value = |
| 141 static_cast<uint32_t>(Smi::cast(*layout_descriptor)->value()); |
| 142 new_layout_descriptor->set(0, value); |
| 143 return new_layout_descriptor; |
| 144 } |
| 145 } |
| 146 } |
| 147 } // namespace v8::internal |
OLD | NEW |