Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(269)

Unified Diff: src/objects.cc

Issue 1197133003: Move SetFastElementsCapacity into GrowCapacityAndConvert (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/objects.h ('k') | src/runtime/runtime-array.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index f2d617b8298e93d45d9dfb580f8549a7bfbfb0fa..86a3343ca6b9e0b405422530c09bc2c11fed2428 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -3389,7 +3389,10 @@ MaybeHandle<Object> Object::AddDataProperty(LookupIterator* it,
}
}
- return JSObject::AddDataElement(receiver, it->index(), value, attributes);
+ MaybeHandle<Object> result =
+ JSObject::AddDataElement(receiver, it->index(), value, attributes);
+ JSObject::ValidateElements(receiver);
+ return result;
} else {
// Migrate to the most up-to-date map that will be able to store |value|
// under it->name() with |attributes|.
@@ -11802,89 +11805,6 @@ void Code::Disassemble(const char* name, std::ostream& os) { // NOLINT
#endif // ENABLE_DISASSEMBLER
-Handle<FixedArray> JSObject::SetFastElementsCapacity(
- Handle<JSObject> object, int capacity,
- SetFastElementsCapacitySmiMode smi_mode) {
- // We should never end in here with a pixel or external array.
- DCHECK(!object->HasExternalArrayElements());
-
- // Allocate a new fast elements backing store.
- Isolate* isolate = object->GetIsolate();
- Handle<FixedArray> new_elements =
- isolate->factory()->NewUninitializedFixedArray(capacity);
-
- isolate->UpdateArrayProtectorOnSetLength(object);
-
- ElementsKind elements_kind = object->GetElementsKind();
- ElementsKind new_elements_kind;
- // The resized array has FAST_*_SMI_ELEMENTS if the capacity mode forces it,
- // or if it's allowed and the old elements array contained only SMIs.
- bool has_fast_smi_elements =
- (smi_mode == kForceSmiElements) ||
- ((smi_mode == kAllowSmiElements) && object->HasFastSmiElements());
- if (has_fast_smi_elements) {
- if (IsHoleyElementsKind(elements_kind)) {
- new_elements_kind = FAST_HOLEY_SMI_ELEMENTS;
- } else {
- new_elements_kind = FAST_SMI_ELEMENTS;
- }
- } else {
- if (IsHoleyElementsKind(elements_kind)) {
- new_elements_kind = FAST_HOLEY_ELEMENTS;
- } else {
- new_elements_kind = FAST_ELEMENTS;
- }
- }
- Handle<FixedArrayBase> old_elements(object->elements());
- ElementsAccessor* accessor = ElementsAccessor::ForKind(new_elements_kind);
- accessor->CopyElements(object, new_elements, elements_kind);
-
- if (elements_kind == SLOPPY_ARGUMENTS_ELEMENTS) {
- Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(old_elements);
- parameter_map->set(1, *new_elements);
- } else {
- Handle<Map> new_map = (new_elements_kind != elements_kind)
- ? GetElementsTransitionMap(object, new_elements_kind)
- : handle(object->map());
- JSObject::ValidateElements(object);
- JSObject::SetMapAndElements(object, new_map, new_elements);
-
- // Transition through the allocation site as well if present.
- JSObject::UpdateAllocationSite(object, new_elements_kind);
- }
-
- if (FLAG_trace_elements_transitions) {
- PrintElementsTransition(stdout, object, elements_kind, old_elements,
- object->GetElementsKind(), new_elements);
- }
-
- return new_elements;
-}
-
-
-Handle<FixedArray> JSObject::SetFastElementsCapacityAndLength(
- Handle<JSObject> object, int capacity, int length,
- SetFastElementsCapacitySmiMode smi_mode) {
- Handle<FixedArray> new_elements =
- SetFastElementsCapacity(object, capacity, smi_mode);
- if (object->IsJSArray()) {
- Handle<JSArray>::cast(object)->set_length(Smi::FromInt(length));
- }
- return new_elements;
-}
-
-
-void JSObject::SetFastDoubleElementsCapacityAndLength(Handle<JSObject> object,
- int capacity,
- int length) {
- ElementsAccessor* accessor = ElementsAccessor::ForKind(FAST_DOUBLE_ELEMENTS);
- accessor->GrowCapacityAndConvert(object, capacity);
- if (object->IsJSArray()) {
- Handle<JSArray>::cast(object)->set_length(Smi::FromInt(length));
- }
-}
-
-
// static
void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) {
DCHECK(capacity >= 0);
@@ -12438,28 +12358,20 @@ void JSObject::AddFastElement(Handle<JSObject> object, uint32_t index,
DCHECK(object->HasFastSmiOrObjectElements() ||
object->HasFastArgumentsElements());
- Isolate* isolate = object->GetIsolate();
-
Handle<FixedArray> backing_store(FixedArray::cast(object->elements()));
if (object->HasSloppyArgumentsElements()) {
backing_store = handle(FixedArray::cast(backing_store->get(1)));
} else {
- // Array optimizations rely on the prototype lookups of Array objects always
- // returning undefined. If there is a store to the initial prototype object,
- // make sure all of these optimizations are invalidated.
- isolate->UpdateArrayProtectorOnSetElement(object);
backing_store = EnsureWritableFastElements(object);
}
uint32_t capacity = static_cast<uint32_t>(backing_store->length());
- uint32_t new_capacity = capacity;
// Check if the length property of this object needs to be updated.
uint32_t array_length = 0;
bool must_update_array_length = false;
bool introduces_holes = true;
if (object->IsJSArray()) {
- CHECK(
- Handle<JSArray>::cast(object)->length()->ToArrayLength(&array_length));
+ CHECK(JSArray::cast(*object)->length()->ToArrayLength(&array_length));
introduces_holes = index > array_length;
if (index >= array_length) {
must_update_array_length = true;
@@ -12469,24 +12381,15 @@ void JSObject::AddFastElement(Handle<JSObject> object, uint32_t index,
introduces_holes = index >= capacity;
}
- // If the array is growing, and it's not growth by a single element at the
- // end, make sure that the ElementsKind is HOLEY.
- if (introduces_holes && !IsFastHoleyElementsKind(object->GetElementsKind())) {
- ElementsKind transitioned_kind =
- GetHoleyElementsKind(object->GetElementsKind());
- TransitionElementsKind(object, transitioned_kind);
- }
-
+ uint32_t new_capacity = capacity;
// Check if the capacity of the backing store needs to be increased, or if
// a transition to slow elements is necessary.
if (index >= capacity) {
bool convert_to_slow = true;
if ((index - capacity) < kMaxGap) {
new_capacity = NewElementsCapacity(index + 1);
- DCHECK(new_capacity > index);
- if (!object->ShouldConvertToSlowElements(new_capacity)) {
- convert_to_slow = false;
- }
+ DCHECK_LT(index, new_capacity);
+ convert_to_slow = object->ShouldConvertToSlowElements(new_capacity);
}
if (convert_to_slow) {
NormalizeElements(object);
@@ -12498,50 +12401,50 @@ void JSObject::AddFastElement(Handle<JSObject> object, uint32_t index,
if (object->HasFastSmiElements() && !value->IsSmi()) {
// Convert to fast double elements if appropriate.
if (value->IsNumber()) {
- // Consider fixing the boilerplate as well if we have one.
- ElementsKind to_kind = IsHoleyElementsKind(object->GetElementsKind())
- ? FAST_HOLEY_DOUBLE_ELEMENTS
- : FAST_DOUBLE_ELEMENTS;
-
- UpdateAllocationSite(object, to_kind);
-
- SetFastDoubleElementsCapacityAndLength(object, new_capacity,
- array_length);
- FixedDoubleArray::cast(object->elements())->set(index, value->Number());
- JSObject::ValidateElements(object);
+ ElementsKind to_kind =
+ introduces_holes ? FAST_HOLEY_DOUBLE_ELEMENTS : FAST_DOUBLE_ELEMENTS;
+ ElementsAccessor* accessor = ElementsAccessor::ForKind(to_kind);
+ accessor->GrowCapacityAndConvert(object, new_capacity);
+ AddFastDoubleElement(object, index, value);
return;
}
// Change elements kind from Smi-only to generic FAST if necessary.
- ElementsKind kind = object->HasFastHoleyElements()
- ? FAST_HOLEY_ELEMENTS
- : FAST_ELEMENTS;
+ ElementsKind kind = introduces_holes || object->HasFastHoleyElements()
+ ? FAST_HOLEY_ELEMENTS
+ : FAST_ELEMENTS;
UpdateAllocationSite(object, kind);
Handle<Map> new_map = GetElementsTransitionMap(object, kind);
JSObject::MigrateToMap(object, new_map);
DCHECK(IsFastObjectElementsKind(object->GetElementsKind()));
+ } else if (introduces_holes && !object->HasFastHoleyElements()) {
+ // If the array is growing, and it's not growth by a single element at the
+ // end, make sure that the ElementsKind is HOLEY.
+ ElementsKind transitioned_kind =
+ GetHoleyElementsKind(object->GetElementsKind());
+ TransitionElementsKind(object, transitioned_kind);
}
// Increase backing store capacity if that's been decided previously.
- // Otherwise, set the new element and length.
- if (new_capacity == capacity) {
- DCHECK(object->elements()->IsFixedArray());
- backing_store->set(index, *value);
- if (must_update_array_length) {
- Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length));
- }
- } else {
- SetFastElementsCapacitySmiMode smi_mode =
- value->IsSmi() && object->HasFastSmiElements()
- ? kAllowSmiElements
- : kDontAllowSmiElements;
- Handle<FixedArray> new_elements =
- SetFastElementsCapacityAndLength(object, new_capacity, array_length,
- smi_mode);
- new_elements->set(index, *value);
- JSObject::ValidateElements(object);
+ if (capacity != new_capacity) {
+ DCHECK(!object->HasFastDoubleElements());
+ ElementsAccessor* accessor =
+ value->IsSmi() || object->HasSloppyArgumentsElements()
+ ? object->GetElementsAccessor()
+ : ElementsAccessor::ForKind(FAST_ELEMENTS);
+ accessor->GrowCapacityAndConvert(object, new_capacity);
}
+
+ if (must_update_array_length) {
+ Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length));
+ }
+
+ FixedArray* elements = FixedArray::cast(object->elements());
+ if (object->HasSloppyArgumentsElements()) {
+ elements = FixedArray::cast(elements->get(1));
+ }
+ elements->set(index, *value);
}
@@ -12701,19 +12604,9 @@ void JSObject::AddDictionaryElement(Handle<JSObject> object, uint32_t index,
} else {
new_length = dictionary->max_number_key() + 1;
}
- bool has_smi_only_elements = false;
- bool should_convert_to_fast_double_elements =
- object->ShouldConvertToFastDoubleElements(&has_smi_only_elements);
- SetFastElementsCapacitySmiMode smi_mode =
- has_smi_only_elements ? kForceSmiElements : kAllowSmiElements;
-
- if (should_convert_to_fast_double_elements) {
- SetFastDoubleElementsCapacityAndLength(object, new_length, new_length);
- } else {
- SetFastElementsCapacityAndLength(object, new_length, new_length,
- smi_mode);
- }
- JSObject::ValidateElements(object);
+ ElementsKind to_kind = object->BestFittingFastElementsKind();
+ ElementsAccessor* accessor = ElementsAccessor::ForKind(to_kind);
+ accessor->GrowCapacityAndConvert(object, new_length);
#ifdef DEBUG
if (FLAG_trace_normalization) {
OFStream os(stdout);
@@ -12730,72 +12623,70 @@ void JSObject::AddFastDoubleElement(Handle<JSObject> object, uint32_t index,
DCHECK(object->HasFastDoubleElements());
Handle<FixedArrayBase> base_elms(FixedArrayBase::cast(object->elements()));
- uint32_t elms_length = static_cast<uint32_t>(base_elms->length());
- uint32_t length = elms_length;
+ uint32_t capacity = static_cast<uint32_t>(base_elms->length());
+ // Check if the length property of this object needs to be updated.
+ uint32_t array_length = 0;
+ bool must_update_array_length = false;
bool introduces_holes = true;
if (object->IsJSArray()) {
// In case of JSArray, the length does not equal the capacity.
- CHECK(Handle<JSArray>::cast(object)->length()->ToArrayLength(&length));
- introduces_holes = index > length;
+ CHECK(JSArray::cast(*object)->length()->ToArrayLength(&array_length));
+ introduces_holes = index > array_length;
+ if (index >= array_length) {
+ must_update_array_length = true;
+ array_length = index + 1;
+ }
} else {
- introduces_holes = index >= elms_length;
+ introduces_holes = index >= capacity;
+ }
+
+ uint32_t new_capacity = capacity;
+ // Check if the capacity of the backing store needs to be increased, or if
+ // a transition to slow elements is necessary.
+ if (index >= capacity) {
+ bool convert_to_slow = true;
+ if ((index - capacity) < kMaxGap) {
+ new_capacity = NewElementsCapacity(index + 1);
+ DCHECK_LT(index, new_capacity);
+ convert_to_slow = object->ShouldConvertToSlowElements(new_capacity);
+ }
+ if (convert_to_slow) {
+ NormalizeElements(object);
+ AddDictionaryElement(object, index, value, NONE);
+ return;
+ }
}
// If the value object is not a heap number, switch to fast elements and try
// again.
if (!value->IsNumber()) {
- SetFastElementsCapacityAndLength(object, elms_length, length,
- kDontAllowSmiElements);
- AddFastElement(object, index, value);
- return;
+ ElementsKind to_kind =
+ introduces_holes ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS;
+ ElementsAccessor* accessor = ElementsAccessor::ForKind(to_kind);
+ accessor->GrowCapacityAndConvert(object, new_capacity);
+ return AddFastElement(object, index, value);
}
// If the array is growing, and it's not growth by a single element at the
// end, make sure that the ElementsKind is HOLEY.
- if (introduces_holes && !IsFastHoleyElementsKind(object->GetElementsKind())) {
- ElementsKind transitioned_kind = FAST_HOLEY_DOUBLE_ELEMENTS;
+ if (introduces_holes && !object->HasFastHoleyElements()) {
+ ElementsKind transitioned_kind =
+ GetHoleyElementsKind(object->GetElementsKind());
TransitionElementsKind(object, transitioned_kind);
}
- // Check whether there is extra space in the fixed array.
- if (index < elms_length) {
- Handle<FixedDoubleArray> elms(FixedDoubleArray::cast(object->elements()));
- elms->set(index, value->Number());
- if (object->IsJSArray()) {
- // Update the length of the array if needed.
- uint32_t array_length = 0;
- CHECK(Handle<JSArray>::cast(object)->length()->ToArrayLength(
- &array_length));
- if (index >= array_length) {
- Handle<JSArray>::cast(object)->set_length(Smi::FromInt(index + 1));
- }
- }
- return;
+ // Increase backing store capacity if that's been decided previously.
+ if (capacity != new_capacity) {
+ ElementsAccessor* accessor = object->GetElementsAccessor();
+ accessor->GrowCapacityAndConvert(object, new_capacity);
}
- // Allow gap in fast case.
- if ((index - elms_length) < kMaxGap) {
- // Try allocating extra space.
- int new_capacity = NewElementsCapacity(index+1);
- if (!object->ShouldConvertToSlowElements(new_capacity)) {
- DCHECK(static_cast<uint32_t>(new_capacity) > index);
- SetFastDoubleElementsCapacityAndLength(object, new_capacity, index + 1);
- FixedDoubleArray::cast(object->elements())->set(index, value->Number());
- JSObject::ValidateElements(object);
- return;
- }
+ if (must_update_array_length) {
+ Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length));
}
- // Otherwise default to slow case.
- DCHECK(object->HasFastDoubleElements());
- DCHECK(object->map()->has_fast_double_elements());
- DCHECK(object->elements()->IsFixedDoubleArray() ||
- object->elements()->length() == 0);
-
- NormalizeElements(object);
- DCHECK(object->HasDictionaryElements());
- AddDictionaryElement(object, index, value, NONE);
+ FixedDoubleArray::cast(object->elements())->set(index, value->Number());
}
@@ -13023,25 +12914,23 @@ void JSObject::UpdateAllocationSite(Handle<JSObject> object,
void JSObject::TransitionElementsKind(Handle<JSObject> object,
ElementsKind to_kind) {
- ElementsKind from_kind = object->map()->elements_kind();
+ ElementsKind from_kind = object->GetElementsKind();
if (IsFastHoleyElementsKind(from_kind)) {
to_kind = GetHoleyElementsKind(to_kind);
}
if (from_kind == to_kind) return;
- // Don't update the site if to_kind isn't fast
- if (IsFastElementsKind(to_kind)) {
- UpdateAllocationSite(object, to_kind);
- }
- Isolate* isolate = object->GetIsolate();
- if (object->elements() == isolate->heap()->empty_fixed_array() ||
- (IsFastSmiOrObjectElementsKind(from_kind) &&
- IsFastSmiOrObjectElementsKind(to_kind)) ||
- (from_kind == FAST_DOUBLE_ELEMENTS &&
- to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) {
- DCHECK(from_kind != TERMINAL_FAST_ELEMENTS_KIND);
+ // This method should never be called for any other case.
+ DCHECK(IsFastElementsKind(from_kind));
+ DCHECK(IsFastElementsKind(to_kind));
+ DCHECK_NE(TERMINAL_FAST_ELEMENTS_KIND, from_kind);
+
+ UpdateAllocationSite(object, to_kind);
+ if (object->elements() == object->GetHeap()->empty_fixed_array() ||
+ IsFastDoubleElementsKind(from_kind) ==
+ IsFastDoubleElementsKind(to_kind)) {
// No change is needed to the elements() buffer, the transition
// only requires a map change.
Handle<Map> new_map = GetElementsTransitionMap(object, to_kind);
@@ -13050,42 +12939,14 @@ void JSObject::TransitionElementsKind(Handle<JSObject> object,
Handle<FixedArrayBase> elms(object->elements());
PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms);
}
- return;
- }
-
- Handle<FixedArrayBase> elms(object->elements());
- uint32_t capacity = static_cast<uint32_t>(elms->length());
- uint32_t length = capacity;
-
- if (object->IsJSArray()) {
- Object* raw_length = Handle<JSArray>::cast(object)->length();
- if (raw_length->IsUndefined()) {
- // If length is undefined, then JSArray is being initialized and has no
- // elements, assume a length of zero.
- length = 0;
- } else {
- CHECK(raw_length->ToArrayLength(&length));
- }
- }
-
- if (IsFastSmiElementsKind(from_kind) &&
- IsFastDoubleElementsKind(to_kind)) {
- SetFastDoubleElementsCapacityAndLength(object, capacity, length);
- JSObject::ValidateElements(object);
- return;
- }
-
- if (IsFastDoubleElementsKind(from_kind) &&
- IsFastObjectElementsKind(to_kind)) {
- SetFastElementsCapacityAndLength(object, capacity, length,
- kDontAllowSmiElements);
- JSObject::ValidateElements(object);
- return;
+ } else {
+ DCHECK((IsFastSmiElementsKind(from_kind) &&
+ IsFastDoubleElementsKind(to_kind)) ||
+ (IsFastDoubleElementsKind(from_kind) &&
+ IsFastObjectElementsKind(to_kind)));
+ uint32_t c = static_cast<uint32_t>(object->elements()->length());
+ ElementsAccessor::ForKind(to_kind)->GrowCapacityAndConvert(object, c);
}
-
- // This method should never be called for any other case than the ones
- // handled above.
- UNREACHABLE();
}
@@ -13300,29 +13161,23 @@ bool JSObject::ShouldConvertToFastElements() {
}
-bool JSObject::ShouldConvertToFastDoubleElements(
- bool* has_smi_only_elements) {
- *has_smi_only_elements = false;
- if (HasSloppyArgumentsElements()) return false;
- if (FLAG_unbox_double_arrays) {
- DCHECK(HasDictionaryElements());
- SeededNumberDictionary* dictionary = element_dictionary();
- bool found_double = false;
- for (int i = 0; i < dictionary->Capacity(); i++) {
- Object* key = dictionary->KeyAt(i);
- if (key->IsNumber()) {
- Object* value = dictionary->ValueAt(i);
- if (!value->IsNumber()) return false;
- if (!value->IsSmi()) {
- found_double = true;
- }
+ElementsKind JSObject::BestFittingFastElementsKind() {
+ if (HasSloppyArgumentsElements()) return FAST_HOLEY_ELEMENTS;
+ DCHECK(HasDictionaryElements());
+ SeededNumberDictionary* dictionary = element_dictionary();
+ ElementsKind kind = FAST_HOLEY_SMI_ELEMENTS;
+ for (int i = 0; i < dictionary->Capacity(); i++) {
+ Object* key = dictionary->KeyAt(i);
+ if (key->IsNumber()) {
+ Object* value = dictionary->ValueAt(i);
+ if (!value->IsNumber()) return FAST_HOLEY_ELEMENTS;
+ if (!value->IsSmi()) {
+ if (!FLAG_unbox_double_arrays) return FAST_HOLEY_ELEMENTS;
+ kind = FAST_HOLEY_DOUBLE_ELEMENTS;
}
}
- *has_smi_only_elements = !found_double;
- return found_double;
- } else {
- return false;
}
+ return kind;
}
« no previous file with comments | « src/objects.h ('k') | src/runtime/runtime-array.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698