blob: e2d66039fd6492149dade607e21e6dac31218846 [file] [log] [blame]
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <sstream>
#include "src/v8.h"
#include "src/layout-descriptor.h"
namespace v8 {
namespace internal {
Handle<LayoutDescriptor> LayoutDescriptor::New(
Handle<Map> map, Handle<DescriptorArray> descriptors, int num_descriptors) {
Isolate* isolate = descriptors->GetIsolate();
if (!FLAG_unbox_double_fields) return handle(FastPointerLayout(), isolate);
int inobject_properties = map->inobject_properties();
if (inobject_properties == 0) return handle(FastPointerLayout(), isolate);
DCHECK(num_descriptors <= descriptors->number_of_descriptors());
int layout_descriptor_length;
const int kMaxWordsPerField = kDoubleSize / kPointerSize;
if (num_descriptors <= kSmiValueSize / kMaxWordsPerField) {
// Even in the "worst" case (all fields are doubles) it would fit into
// a Smi, so no need to calculate length.
layout_descriptor_length = kSmiValueSize;
} else {
layout_descriptor_length = 0;
for (int i = 0; i < num_descriptors; i++) {
PropertyDetails details = descriptors->GetDetails(i);
if (!InobjectUnboxedField(inobject_properties, details)) continue;
int field_index = details.field_index();
int field_width_in_words = details.field_width_in_words();
layout_descriptor_length =
Max(layout_descriptor_length, field_index + field_width_in_words);
}
if (layout_descriptor_length == 0) {
// No double fields were found, use fast pointer layout.
return handle(FastPointerLayout(), isolate);
}
}
layout_descriptor_length = Min(layout_descriptor_length, inobject_properties);
// Initially, layout descriptor corresponds to an object with all fields
// tagged.
Handle<LayoutDescriptor> layout_descriptor_handle =
LayoutDescriptor::New(isolate, layout_descriptor_length);
DisallowHeapAllocation no_allocation;
LayoutDescriptor* layout_descriptor = *layout_descriptor_handle;
for (int i = 0; i < num_descriptors; i++) {
PropertyDetails details = descriptors->GetDetails(i);
if (!InobjectUnboxedField(inobject_properties, details)) continue;
int field_index = details.field_index();
layout_descriptor = layout_descriptor->SetRawData(field_index);
if (details.field_width_in_words() > 1) {
layout_descriptor = layout_descriptor->SetRawData(field_index + 1);
}
}
return handle(layout_descriptor, isolate);
}
Handle<LayoutDescriptor> LayoutDescriptor::Append(Handle<Map> map,
PropertyDetails details) {
Isolate* isolate = map->GetIsolate();
Handle<LayoutDescriptor> layout_descriptor(map->GetLayoutDescriptor(),
isolate);
if (!InobjectUnboxedField(map->inobject_properties(), details)) {
return layout_descriptor;
}
int field_index = details.field_index();
layout_descriptor = LayoutDescriptor::EnsureCapacity(
isolate, layout_descriptor, field_index + details.field_width_in_words());
DisallowHeapAllocation no_allocation;
LayoutDescriptor* layout_desc = *layout_descriptor;
layout_desc = layout_desc->SetRawData(field_index);
if (details.field_width_in_words() > 1) {
layout_desc = layout_desc->SetRawData(field_index + 1);
}
return handle(layout_desc, isolate);
}
Handle<LayoutDescriptor> LayoutDescriptor::AppendIfFastOrUseFull(
Handle<Map> map, PropertyDetails details,
Handle<LayoutDescriptor> full_layout_descriptor) {
DisallowHeapAllocation no_allocation;
LayoutDescriptor* layout_descriptor = map->layout_descriptor();
if (layout_descriptor->IsSlowLayout()) {
return full_layout_descriptor;
}
if (!InobjectUnboxedField(map->inobject_properties(), details)) {
return handle(layout_descriptor, map->GetIsolate());
}
int field_index = details.field_index();
int new_capacity = field_index + details.field_width_in_words();
if (new_capacity > layout_descriptor->capacity()) {
// Current map's layout descriptor runs out of space, so use the full
// layout descriptor.
return full_layout_descriptor;
}
layout_descriptor = layout_descriptor->SetRawData(field_index);
if (details.field_width_in_words() > 1) {
layout_descriptor = layout_descriptor->SetRawData(field_index + 1);
}
return handle(layout_descriptor, map->GetIsolate());
}
Handle<LayoutDescriptor> LayoutDescriptor::EnsureCapacity(
Isolate* isolate, Handle<LayoutDescriptor> layout_descriptor,
int new_capacity) {
int old_capacity = layout_descriptor->capacity();
if (new_capacity <= old_capacity) {
// Nothing to do with layout in Smi-form.
return layout_descriptor;
}
Handle<LayoutDescriptor> new_layout_descriptor =
LayoutDescriptor::New(isolate, new_capacity);
DCHECK(new_layout_descriptor->IsSlowLayout());
if (layout_descriptor->IsSlowLayout()) {
memcpy(new_layout_descriptor->DataPtr(), layout_descriptor->DataPtr(),
layout_descriptor->DataSize());
return new_layout_descriptor;
} else {
// Fast layout.
uint32_t value =
static_cast<uint32_t>(Smi::cast(*layout_descriptor)->value());
new_layout_descriptor->set(0, value);
return new_layout_descriptor;
}
}
}
} // namespace v8::internal