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

Unified Diff: src/objects.cc

Issue 10442015: Rollback of r11638, r11636 on trunk branch. (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: Created 8 years, 7 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/objects-debug.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 8cf7a58256c5b3b65b1dc1e811b6fd15fc83f457..cb87c71fb1193c38953701a88ffac4e1f465d9cd 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -56,6 +56,11 @@
namespace v8 {
namespace internal {
+void PrintElementsKind(FILE* out, ElementsKind kind) {
+ ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
+ PrintF(out, "%s", accessor->name());
+}
+
MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor,
Object* value) {
@@ -538,7 +543,7 @@ bool JSObject::IsDirty() {
// If the object is fully fast case and has the same map it was
// created with then no changes can have been made to it.
return map() != fun->initial_map()
- || !HasFastObjectElements()
+ || !HasFastElements()
|| !HasFastProperties();
}
@@ -1062,9 +1067,7 @@ void String::StringShortPrint(StringStream* accumulator) {
void JSObject::JSObjectShortPrint(StringStream* accumulator) {
switch (map()->instance_type()) {
case JS_ARRAY_TYPE: {
- double length = JSArray::cast(this)->length()->IsUndefined()
- ? 0
- : JSArray::cast(this)->length()->Number();
+ double length = JSArray::cast(this)->length()->Number();
accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length));
break;
}
@@ -2199,29 +2202,34 @@ static Handle<T> MaybeNull(T* p) {
Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) {
- ElementsKind kind = elements_kind();
- Handle<Map> transitioned_map = Handle<Map>::null();
- Handle<Map> current_map(this);
- bool packed = IsFastPackedElementsKind(kind);
- if (IsTransitionableFastElementsKind(kind)) {
- while (CanTransitionToMoreGeneralFastElementsKind(kind, false)) {
- kind = GetNextMoreGeneralFastElementsKind(kind, false);
- bool dummy = true;
- Handle<Map> maybe_transitioned_map =
- MaybeNull(current_map->LookupElementsTransitionMap(kind, &dummy));
- if (maybe_transitioned_map.is_null()) break;
- if (ContainsMap(candidates, maybe_transitioned_map) &&
- (packed || !IsFastPackedElementsKind(kind))) {
- transitioned_map = maybe_transitioned_map;
- if (!IsFastPackedElementsKind(kind)) packed = false;
- }
- current_map = maybe_transitioned_map;
- }
- }
- return transitioned_map;
+ ElementsKind elms_kind = elements_kind();
+ if (elms_kind == FAST_DOUBLE_ELEMENTS) {
+ bool dummy = true;
+ Handle<Map> fast_map =
+ MaybeNull(LookupElementsTransitionMap(FAST_ELEMENTS, &dummy));
+ if (!fast_map.is_null() && ContainsMap(candidates, fast_map)) {
+ return fast_map;
+ }
+ return Handle<Map>::null();
+ }
+ if (elms_kind == FAST_SMI_ONLY_ELEMENTS) {
+ bool dummy = true;
+ Handle<Map> double_map =
+ MaybeNull(LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, &dummy));
+ // In the current implementation, if the DOUBLE map doesn't exist, the
+ // FAST map can't exist either.
+ if (double_map.is_null()) return Handle<Map>::null();
+ Handle<Map> fast_map =
+ MaybeNull(double_map->LookupElementsTransitionMap(FAST_ELEMENTS,
+ &dummy));
+ if (!fast_map.is_null() && ContainsMap(candidates, fast_map)) {
+ return fast_map;
+ }
+ if (ContainsMap(candidates, double_map)) return double_map;
+ }
+ return Handle<Map>::null();
}
-
static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents,
ElementsKind elements_kind) {
if (descriptor_contents->IsMap()) {
@@ -2330,36 +2338,24 @@ Object* Map::GetDescriptorContents(String* sentinel_name,
}
-Map* Map::LookupElementsTransitionMap(ElementsKind to_kind,
+Map* Map::LookupElementsTransitionMap(ElementsKind elements_kind,
bool* safe_to_add_transition) {
- ElementsKind from_kind = elements_kind();
- if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) {
- if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
- if (safe_to_add_transition) *safe_to_add_transition = false;
- return NULL;
- }
- ElementsKind transitioned_from_kind =
- GetNextMoreGeneralFastElementsKind(from_kind, false);
-
-
- // If the transition is a single step in the transition sequence, fall
- // through to looking it up and returning it. If it requires several steps,
- // divide and conquer.
- if (transitioned_from_kind != to_kind) {
- // If the transition is several steps in the lattice, divide and conquer.
- Map* from_map = LookupElementsTransitionMap(transitioned_from_kind,
- safe_to_add_transition);
- if (from_map == NULL) return NULL;
- return from_map->LookupElementsTransitionMap(to_kind,
+ // Special case: indirect SMI->FAST transition (cf. comment in
+ // AddElementsTransition()).
+ if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS &&
+ elements_kind == FAST_ELEMENTS) {
+ Map* double_map = this->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS,
+ safe_to_add_transition);
+ if (double_map == NULL) return double_map;
+ return double_map->LookupElementsTransitionMap(FAST_ELEMENTS,
safe_to_add_transition);
- }
}
Object* descriptor_contents = GetDescriptorContents(
elements_transition_sentinel_name(), safe_to_add_transition);
if (descriptor_contents != NULL) {
Map* maybe_transition_map =
GetElementsTransitionMapFromDescriptor(descriptor_contents,
- to_kind);
+ elements_kind);
ASSERT(maybe_transition_map == NULL || maybe_transition_map->IsMap());
return maybe_transition_map;
}
@@ -2367,35 +2363,29 @@ Map* Map::LookupElementsTransitionMap(ElementsKind to_kind,
}
-MaybeObject* Map::AddElementsTransition(ElementsKind to_kind,
+MaybeObject* Map::AddElementsTransition(ElementsKind elements_kind,
Map* transitioned_map) {
- ElementsKind from_kind = elements_kind();
- if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) {
- ASSERT(IsMoreGeneralElementsKindTransition(from_kind, to_kind));
- ElementsKind transitioned_from_kind =
- GetNextMoreGeneralFastElementsKind(from_kind, false);
- // The map transitions graph should be a tree, therefore transitions to
- // ElementsKind that are not adjacent in the ElementsKind sequence are not
- // done directly, but instead by going through intermediate ElementsKinds
- // first.
- if (to_kind != transitioned_from_kind) {
- bool safe_to_add = true;
- Map* intermediate_map = LookupElementsTransitionMap(
- transitioned_from_kind, &safe_to_add);
- // This method is only called when safe_to_add has been found to be true
- // earlier.
- ASSERT(safe_to_add);
-
- if (intermediate_map == NULL) {
- MaybeObject* maybe_map = CopyDropTransitions();
- if (!maybe_map->To(&intermediate_map)) return maybe_map;
- intermediate_map->set_elements_kind(transitioned_from_kind);
- MaybeObject* maybe_transition = AddElementsTransition(
- transitioned_from_kind, intermediate_map);
- if (maybe_transition->IsFailure()) return maybe_transition;
- }
- return intermediate_map->AddElementsTransition(to_kind, transitioned_map);
- }
+ // The map transition graph should be a tree, therefore the transition
+ // from SMI to FAST elements is not done directly, but by going through
+ // DOUBLE elements first.
+ if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS &&
+ elements_kind == FAST_ELEMENTS) {
+ bool safe_to_add = true;
+ Map* double_map = this->LookupElementsTransitionMap(
+ FAST_DOUBLE_ELEMENTS, &safe_to_add);
+ // This method is only called when safe_to_add_transition has been found
+ // to be true earlier.
+ ASSERT(safe_to_add);
+
+ if (double_map == NULL) {
+ MaybeObject* maybe_map = this->CopyDropTransitions();
+ if (!maybe_map->To(&double_map)) return maybe_map;
+ double_map->set_elements_kind(FAST_DOUBLE_ELEMENTS);
+ MaybeObject* maybe_double_transition = this->AddElementsTransition(
+ FAST_DOUBLE_ELEMENTS, double_map);
+ if (maybe_double_transition->IsFailure()) return maybe_double_transition;
+ }
+ return double_map->AddElementsTransition(FAST_ELEMENTS, transitioned_map);
}
bool safe_to_add_transition = true;
@@ -2447,11 +2437,10 @@ MaybeObject* JSObject::GetElementsTransitionMapSlow(ElementsKind to_kind) {
!current_map->IsUndefined() &&
!current_map->is_shared();
- // Prevent long chains of DICTIONARY -> FAST_*_ELEMENTS maps caused by objects
+ // Prevent long chains of DICTIONARY -> FAST_ELEMENTS maps caused by objects
// with elements that switch back and forth between dictionary and fast
- // element modes.
- if (from_kind == DICTIONARY_ELEMENTS &&
- IsFastElementsKind(to_kind)) {
+ // element mode.
+ if (from_kind == DICTIONARY_ELEMENTS && to_kind == FAST_ELEMENTS) {
safe_to_add_transition = false;
}
@@ -3487,7 +3476,8 @@ MaybeObject* JSObject::NormalizeElements() {
}
if (array->IsDictionary()) return array;
- ASSERT(HasFastSmiOrObjectElements() ||
+ ASSERT(HasFastElements() ||
+ HasFastSmiOnlyElements() ||
HasFastDoubleElements() ||
HasFastArgumentsElements());
// Compute the effective length and allocate a new backing store.
@@ -3522,7 +3512,8 @@ MaybeObject* JSObject::NormalizeElements() {
if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
}
} else {
- ASSERT(old_map->has_fast_smi_or_object_elements());
+ ASSERT(old_map->has_fast_elements() ||
+ old_map->has_fast_smi_only_elements());
value = FixedArray::cast(array)->get(i);
}
PropertyDetails details = PropertyDetails(NONE, NORMAL);
@@ -4009,9 +4000,9 @@ MaybeObject* JSReceiver::DeleteProperty(String* name, DeleteMode mode) {
bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
ElementsKind kind,
Object* object) {
- ASSERT(IsFastObjectElementsKind(kind) ||
+ ASSERT(kind == FAST_ELEMENTS ||
kind == DICTIONARY_ELEMENTS);
- if (IsFastObjectElementsKind(kind)) {
+ if (kind == FAST_ELEMENTS) {
int length = IsJSArray()
? Smi::cast(JSArray::cast(this)->length())->value()
: elements->length();
@@ -4063,15 +4054,12 @@ bool JSObject::ReferencesObject(Object* obj) {
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
- case FAST_HOLEY_DOUBLE_ELEMENTS:
// Raw pixels and external arrays do not reference other
// objects.
break;
- case FAST_SMI_ELEMENTS:
- case FAST_HOLEY_SMI_ELEMENTS:
+ case FAST_SMI_ONLY_ELEMENTS:
break;
case FAST_ELEMENTS:
- case FAST_HOLEY_ELEMENTS:
case DICTIONARY_ELEMENTS: {
FixedArray* elements = FixedArray::cast(this->elements());
if (ReferencesObjectFromElements(elements, kind, obj)) return true;
@@ -4087,8 +4075,7 @@ bool JSObject::ReferencesObject(Object* obj) {
}
// Check the arguments.
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
- kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS :
- FAST_HOLEY_ELEMENTS;
+ kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS;
if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
break;
}
@@ -4322,7 +4309,7 @@ void JSReceiver::Lookup(String* name, LookupResult* result) {
}
-// Search object and its prototype chain for callback properties.
+// Search object and it's prototype chain for callback properties.
void JSObject::LookupCallback(String* name, LookupResult* result) {
Heap* heap = GetHeap();
for (Object* current = this;
@@ -4366,12 +4353,9 @@ MaybeObject* JSObject::DefineElementAccessor(uint32_t index,
Object* setter,
PropertyAttributes attributes) {
switch (GetElementsKind()) {
- case FAST_SMI_ELEMENTS:
+ case FAST_SMI_ONLY_ELEMENTS:
case FAST_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
- case FAST_HOLEY_SMI_ELEMENTS:
- case FAST_HOLEY_ELEMENTS:
- case FAST_HOLEY_DOUBLE_ELEMENTS:
break;
case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_BYTE_ELEMENTS:
@@ -4461,7 +4445,7 @@ bool JSObject::CanSetCallback(String* name) {
GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET));
// Check if there is an API defined callback object which prohibits
- // callback overwriting in this object or its prototype chain.
+ // callback overwriting in this object or it's prototype chain.
// This mechanism is needed for instance in a browser setting, where
// certain accessors such as window.location should not be allowed
// to be overwritten because allowing overwriting could potentially
@@ -4632,12 +4616,9 @@ MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) {
// Accessors overwrite previous callbacks (cf. with getters/setters).
switch (GetElementsKind()) {
- case FAST_SMI_ELEMENTS:
+ case FAST_SMI_ONLY_ELEMENTS:
case FAST_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
- case FAST_HOLEY_SMI_ELEMENTS:
- case FAST_HOLEY_ELEMENTS:
- case FAST_HOLEY_DOUBLE_ELEMENTS:
break;
case EXTERNAL_PIXEL_ELEMENTS:
case EXTERNAL_BYTE_ELEMENTS:
@@ -8426,7 +8407,7 @@ void Code::Disassemble(const char* name, FILE* out) {
MaybeObject* JSObject::SetFastElementsCapacityAndLength(
int capacity,
int length,
- SetFastElementsCapacitySmiMode smi_mode) {
+ SetFastElementsCapacityMode set_capacity_mode) {
Heap* heap = GetHeap();
// We should never end in here with a pixel or external array.
ASSERT(!HasExternalArrayElements());
@@ -8437,40 +8418,34 @@ MaybeObject* JSObject::SetFastElementsCapacityAndLength(
if (!maybe->To(&new_elements)) return maybe;
}
- ElementsKind elements_kind = 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) && 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;
- }
+ // Find the new map to use for this object if there is a map change.
+ Map* new_map = NULL;
+ if (elements()->map() != heap->non_strict_arguments_elements_map()) {
+ // The resized array has FAST_SMI_ONLY_ELEMENTS if the capacity mode forces
+ // it, or if it's allowed and the old elements array contained only SMIs.
+ bool has_fast_smi_only_elements =
+ (set_capacity_mode == kForceSmiOnlyElements) ||
+ ((set_capacity_mode == kAllowSmiOnlyElements) &&
+ (elements()->map()->has_fast_smi_only_elements() ||
+ elements() == heap->empty_fixed_array()));
+ ElementsKind elements_kind = has_fast_smi_only_elements
+ ? FAST_SMI_ONLY_ELEMENTS
+ : FAST_ELEMENTS;
+ MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), elements_kind);
+ if (!maybe->To(&new_map)) return maybe;
}
+
FixedArrayBase* old_elements = elements();
+ ElementsKind elements_kind = GetElementsKind();
ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
+ ElementsKind to_kind = (elements_kind == FAST_SMI_ONLY_ELEMENTS)
+ ? FAST_SMI_ONLY_ELEMENTS
+ : FAST_ELEMENTS;
{ MaybeObject* maybe_obj =
- accessor->CopyElements(this, new_elements, new_elements_kind);
+ accessor->CopyElements(this, new_elements, to_kind);
if (maybe_obj->IsFailure()) return maybe_obj;
}
if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
- Map* new_map = map();
- if (new_elements_kind != elements_kind) {
- MaybeObject* maybe =
- GetElementsTransitionMap(GetIsolate(), new_elements_kind);
- if (!maybe->To(&new_map)) return maybe;
- }
- ValidateElements();
set_map_and_elements(new_map, new_elements);
} else {
FixedArray* parameter_map = FixedArray::cast(old_elements);
@@ -8482,9 +8457,11 @@ MaybeObject* JSObject::SetFastElementsCapacityAndLength(
GetElementsKind(), new_elements);
}
+ // Update the length if necessary.
if (IsJSArray()) {
JSArray::cast(this)->set_length(Smi::FromInt(length));
}
+
return new_elements;
}
@@ -8502,28 +8479,20 @@ MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength(
if (!maybe_obj->To(&elems)) return maybe_obj;
}
- ElementsKind elements_kind = GetElementsKind();
- ElementsKind new_elements_kind = elements_kind;
- if (IsHoleyElementsKind(elements_kind)) {
- new_elements_kind = FAST_HOLEY_DOUBLE_ELEMENTS;
- } else {
- new_elements_kind = FAST_DOUBLE_ELEMENTS;
- }
-
Map* new_map;
{ MaybeObject* maybe_obj =
- GetElementsTransitionMap(heap->isolate(), new_elements_kind);
+ GetElementsTransitionMap(heap->isolate(), FAST_DOUBLE_ELEMENTS);
if (!maybe_obj->To(&new_map)) return maybe_obj;
}
FixedArrayBase* old_elements = elements();
+ ElementsKind elements_kind = GetElementsKind();
ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
{ MaybeObject* maybe_obj =
accessor->CopyElements(this, elems, FAST_DOUBLE_ELEMENTS);
if (maybe_obj->IsFailure()) return maybe_obj;
}
if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
- ValidateElements();
set_map_and_elements(new_map, elems);
} else {
FixedArray* parameter_map = FixedArray::cast(old_elements);
@@ -8532,7 +8501,7 @@ MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength(
if (FLAG_trace_elements_transitions) {
PrintElementsTransition(stdout, elements_kind, old_elements,
- GetElementsKind(), elems);
+ FAST_DOUBLE_ELEMENTS, elems);
}
if (IsJSArray()) {
@@ -8812,10 +8781,8 @@ JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) {
}
switch (GetElementsKind()) {
- case FAST_SMI_ELEMENTS:
- case FAST_ELEMENTS:
- case FAST_HOLEY_SMI_ELEMENTS:
- case FAST_HOLEY_ELEMENTS: {
+ case FAST_SMI_ONLY_ELEMENTS:
+ case FAST_ELEMENTS: {
uint32_t length = IsJSArray() ?
static_cast<uint32_t>
(Smi::cast(JSArray::cast(this)->length())->value()) :
@@ -8826,8 +8793,7 @@ JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) {
}
break;
}
- case FAST_DOUBLE_ELEMENTS:
- case FAST_HOLEY_DOUBLE_ELEMENTS: {
+ case FAST_DOUBLE_ELEMENTS: {
uint32_t length = IsJSArray() ?
static_cast<uint32_t>
(Smi::cast(JSArray::cast(this)->length())->value()) :
@@ -9111,7 +9077,7 @@ MaybeObject* JSObject::SetFastElement(uint32_t index,
Object* value,
StrictModeFlag strict_mode,
bool check_prototype) {
- ASSERT(HasFastSmiOrObjectElements() ||
+ ASSERT(HasFastTypeElements() ||
HasFastArgumentsElements());
FixedArray* backing_store = FixedArray::cast(elements());
@@ -9137,29 +9103,13 @@ MaybeObject* JSObject::SetFastElement(uint32_t index,
// 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 (IsJSArray()) {
CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
- introduces_holes = index > array_length;
if (index >= array_length) {
must_update_array_length = true;
array_length = index + 1;
}
- } else {
- 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.
- ElementsKind elements_kind = GetElementsKind();
- if (introduces_holes &&
- IsFastElementsKind(elements_kind) &&
- !IsFastHoleyElementsKind(elements_kind)) {
- ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
- MaybeObject* maybe = TransitionElementsKind(transitioned_kind);
- if (maybe->IsFailure()) return maybe;
}
-
// Check if the capacity of the backing store needs to be increased, or if
// a transition to slow elements is necessary.
if (index >= capacity) {
@@ -9179,44 +9129,42 @@ MaybeObject* JSObject::SetFastElement(uint32_t index,
}
}
// Convert to fast double elements if appropriate.
- if (HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) {
+ if (HasFastSmiOnlyElements() && !value->IsSmi() && value->IsNumber()) {
MaybeObject* maybe =
SetFastDoubleElementsCapacityAndLength(new_capacity, array_length);
if (maybe->IsFailure()) return maybe;
FixedDoubleArray::cast(elements())->set(index, value->Number());
- ValidateElements();
return value;
}
- // Change elements kind from Smi-only to generic FAST if necessary.
- if (HasFastSmiElements() && !value->IsSmi()) {
+ // Change elements kind from SMI_ONLY to generic FAST if necessary.
+ if (HasFastSmiOnlyElements() && !value->IsSmi()) {
Map* new_map;
- ElementsKind kind = HasFastHoleyElements()
- ? FAST_HOLEY_ELEMENTS
- : FAST_ELEMENTS;
- MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(),
- kind);
- if (!maybe_new_map->To(&new_map)) return maybe_new_map;
-
+ { MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(),
+ FAST_ELEMENTS);
+ if (!maybe_new_map->To(&new_map)) return maybe_new_map;
+ }
set_map(new_map);
+ if (FLAG_trace_elements_transitions) {
+ PrintElementsTransition(stdout, FAST_SMI_ONLY_ELEMENTS, elements(),
+ FAST_ELEMENTS, elements());
+ }
}
// Increase backing store capacity if that's been decided previously.
if (new_capacity != capacity) {
FixedArray* new_elements;
- SetFastElementsCapacitySmiMode smi_mode =
- value->IsSmi() && HasFastSmiElements()
- ? kAllowSmiElements
- : kDontAllowSmiElements;
+ SetFastElementsCapacityMode set_capacity_mode =
+ value->IsSmi() && HasFastSmiOnlyElements()
+ ? kAllowSmiOnlyElements
+ : kDontAllowSmiOnlyElements;
{ MaybeObject* maybe =
SetFastElementsCapacityAndLength(new_capacity,
array_length,
- smi_mode);
+ set_capacity_mode);
if (!maybe->To(&new_elements)) return maybe;
}
new_elements->set(index, value);
- ValidateElements();
return value;
}
-
// Finally, set the new element and length.
ASSERT(elements()->IsFixedArray());
backing_store->set(index, value);
@@ -9340,21 +9288,20 @@ MaybeObject* JSObject::SetDictionaryElement(uint32_t index,
} else {
new_length = dictionary->max_number_key() + 1;
}
- SetFastElementsCapacitySmiMode smi_mode = FLAG_smi_only_arrays
- ? kAllowSmiElements
- : kDontAllowSmiElements;
+ SetFastElementsCapacityMode set_capacity_mode = FLAG_smi_only_arrays
+ ? kAllowSmiOnlyElements
+ : kDontAllowSmiOnlyElements;
bool has_smi_only_elements = false;
bool should_convert_to_fast_double_elements =
ShouldConvertToFastDoubleElements(&has_smi_only_elements);
if (has_smi_only_elements) {
- smi_mode = kForceSmiElements;
+ set_capacity_mode = kForceSmiOnlyElements;
}
MaybeObject* result = should_convert_to_fast_double_elements
? SetFastDoubleElementsCapacityAndLength(new_length, new_length)
: SetFastElementsCapacityAndLength(new_length,
new_length,
- smi_mode);
- ValidateElements();
+ set_capacity_mode);
if (result->IsFailure()) return result;
#ifdef DEBUG
if (FLAG_trace_normalization) {
@@ -9393,40 +9340,27 @@ MUST_USE_RESULT MaybeObject* JSObject::SetFastDoubleElement(
// If the value object is not a heap number, switch to fast elements and try
// again.
bool value_is_smi = value->IsSmi();
- bool introduces_holes = true;
- uint32_t length = elms_length;
- if (IsJSArray()) {
- CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
- introduces_holes = index > length;
- } else {
- introduces_holes = index >= elms_length;
- }
-
if (!value->IsNumber()) {
+ Object* obj;
+ uint32_t length = elms_length;
+ if (IsJSArray()) {
+ CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
+ }
MaybeObject* maybe_obj = SetFastElementsCapacityAndLength(
elms_length,
length,
- kDontAllowSmiElements);
- if (maybe_obj->IsFailure()) return maybe_obj;
- maybe_obj = SetFastElement(index, value, strict_mode, check_prototype);
- if (maybe_obj->IsFailure()) return maybe_obj;
- ValidateElements();
- return maybe_obj;
+ kDontAllowSmiOnlyElements);
+ if (!maybe_obj->ToObject(&obj)) return maybe_obj;
+ return SetFastElement(index,
+ value,
+ strict_mode,
+ check_prototype);
}
double double_value = value_is_smi
? static_cast<double>(Smi::cast(value)->value())
: HeapNumber::cast(value)->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.
- ElementsKind elements_kind = GetElementsKind();
- if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) {
- ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
- MaybeObject* maybe = TransitionElementsKind(transitioned_kind);
- if (maybe->IsFailure()) return maybe;
- }
-
// Check whether there is extra space in the fixed array.
if (index < elms_length) {
FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
@@ -9448,11 +9382,13 @@ MUST_USE_RESULT MaybeObject* JSObject::SetFastDoubleElement(
int new_capacity = NewElementsCapacity(index+1);
if (!ShouldConvertToSlowElements(new_capacity)) {
ASSERT(static_cast<uint32_t>(new_capacity) > index);
- MaybeObject* maybe_obj =
- SetFastDoubleElementsCapacityAndLength(new_capacity, index + 1);
- if (maybe_obj->IsFailure()) return maybe_obj;
+ Object* obj;
+ { MaybeObject* maybe_obj =
+ SetFastDoubleElementsCapacityAndLength(new_capacity,
+ index + 1);
+ if (!maybe_obj->ToObject(&obj)) return maybe_obj;
+ }
FixedDoubleArray::cast(elements())->set(index, double_value);
- ValidateElements();
return value;
}
}
@@ -9596,13 +9532,10 @@ MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
(attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0);
Isolate* isolate = GetIsolate();
switch (GetElementsKind()) {
- case FAST_SMI_ELEMENTS:
+ case FAST_SMI_ONLY_ELEMENTS:
case FAST_ELEMENTS:
- case FAST_HOLEY_SMI_ELEMENTS:
- case FAST_HOLEY_ELEMENTS:
return SetFastElement(index, value, strict_mode, check_prototype);
case FAST_DOUBLE_ELEMENTS:
- case FAST_HOLEY_DOUBLE_ELEMENTS:
return SetFastDoubleElement(index, value, strict_mode, check_prototype);
case EXTERNAL_PIXEL_ELEMENTS: {
ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
@@ -9693,19 +9626,11 @@ Handle<Object> JSObject::TransitionElementsKind(Handle<JSObject> object,
MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) {
ElementsKind from_kind = map()->elements_kind();
- if (IsFastHoleyElementsKind(from_kind)) {
- to_kind = GetHoleyElementsKind(to_kind);
- }
-
Isolate* isolate = GetIsolate();
- if (elements() == isolate->heap()->empty_fixed_array() ||
- (IsFastSmiOrObjectElementsKind(from_kind) &&
- IsFastSmiOrObjectElementsKind(to_kind)) ||
- (from_kind == FAST_DOUBLE_ELEMENTS &&
- to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) {
- ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND);
- // No change is needed to the elements() buffer, the transition
- // only requires a map change.
+ if ((from_kind == FAST_SMI_ONLY_ELEMENTS ||
+ elements() == isolate->heap()->empty_fixed_array()) &&
+ to_kind == FAST_ELEMENTS) {
+ ASSERT(from_kind != FAST_ELEMENTS);
MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind);
Map* new_map;
if (!maybe_new_map->To(&new_map)) return maybe_new_map;
@@ -9732,21 +9657,18 @@ MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) {
}
}
- if (IsFastSmiElementsKind(from_kind) &&
- IsFastDoubleElementsKind(to_kind)) {
+ if (from_kind == FAST_SMI_ONLY_ELEMENTS &&
+ to_kind == FAST_DOUBLE_ELEMENTS) {
MaybeObject* maybe_result =
SetFastDoubleElementsCapacityAndLength(capacity, length);
if (maybe_result->IsFailure()) return maybe_result;
- ValidateElements();
return this;
}
- if (IsFastDoubleElementsKind(from_kind) &&
- IsFastObjectElementsKind(to_kind)) {
+ if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) {
MaybeObject* maybe_result = SetFastElementsCapacityAndLength(
- capacity, length, kDontAllowSmiElements);
+ capacity, length, kDontAllowSmiOnlyElements);
if (maybe_result->IsFailure()) return maybe_result;
- ValidateElements();
return this;
}
@@ -9760,14 +9682,10 @@ MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) {
// static
bool Map::IsValidElementsTransition(ElementsKind from_kind,
ElementsKind to_kind) {
- // Transitions can't go backwards.
- if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
- return false;
- }
-
- // Transitions from HOLEY -> PACKED are not allowed.
- return !IsFastHoleyElementsKind(from_kind) ||
- IsFastHoleyElementsKind(to_kind);
+ return
+ (from_kind == FAST_SMI_ONLY_ELEMENTS &&
+ (to_kind == FAST_DOUBLE_ELEMENTS || to_kind == FAST_ELEMENTS)) ||
+ (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS);
}
@@ -9858,10 +9776,8 @@ void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) {
break;
}
// Fall through.
- case FAST_SMI_ELEMENTS:
+ case FAST_SMI_ONLY_ELEMENTS:
case FAST_ELEMENTS:
- case FAST_HOLEY_SMI_ELEMENTS:
- case FAST_HOLEY_ELEMENTS:
backing_store = FixedArray::cast(backing_store_base);
*capacity = backing_store->length();
for (int i = 0; i < *capacity; ++i) {
@@ -9875,8 +9791,7 @@ void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) {
*used = dictionary->NumberOfElements();
break;
}
- case FAST_DOUBLE_ELEMENTS:
- case FAST_HOLEY_DOUBLE_ELEMENTS: {
+ case FAST_DOUBLE_ELEMENTS: {
FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
*capacity = elms->length();
for (int i = 0; i < *capacity; i++) {
@@ -10146,19 +10061,16 @@ bool JSObject::HasRealElementProperty(uint32_t index) {
if (this->IsStringObjectWithCharacterAt(index)) return true;
switch (GetElementsKind()) {
- case FAST_SMI_ELEMENTS:
- case FAST_ELEMENTS:
- case FAST_HOLEY_SMI_ELEMENTS:
- case FAST_HOLEY_ELEMENTS: {
- uint32_t length = IsJSArray() ?
+ case FAST_SMI_ONLY_ELEMENTS:
+ case FAST_ELEMENTS: {
+ uint32_t length = IsJSArray() ?
static_cast<uint32_t>(
Smi::cast(JSArray::cast(this)->length())->value()) :
static_cast<uint32_t>(FixedArray::cast(elements())->length());
return (index < length) &&
!FixedArray::cast(elements())->get(index)->IsTheHole();
}
- case FAST_DOUBLE_ELEMENTS:
- case FAST_HOLEY_DOUBLE_ELEMENTS: {
+ case FAST_DOUBLE_ELEMENTS: {
uint32_t length = IsJSArray() ?
static_cast<uint32_t>(
Smi::cast(JSArray::cast(this)->length())->value()) :
@@ -10358,7 +10270,7 @@ int JSObject::NumberOfLocalElements(PropertyAttributes filter) {
int JSObject::NumberOfEnumElements() {
// Fast case for objects with no elements.
- if (!IsJSValue() && HasFastObjectElements()) {
+ if (!IsJSValue() && HasFastElements()) {
uint32_t length = IsJSArray() ?
static_cast<uint32_t>(
Smi::cast(JSArray::cast(this)->length())->value()) :
@@ -10374,10 +10286,8 @@ int JSObject::GetLocalElementKeys(FixedArray* storage,
PropertyAttributes filter) {
int counter = 0;
switch (GetElementsKind()) {
- case FAST_SMI_ELEMENTS:
- case FAST_ELEMENTS:
- case FAST_HOLEY_SMI_ELEMENTS:
- case FAST_HOLEY_ELEMENTS: {
+ case FAST_SMI_ONLY_ELEMENTS:
+ case FAST_ELEMENTS: {
int length = IsJSArray() ?
Smi::cast(JSArray::cast(this)->length())->value() :
FixedArray::cast(elements())->length();
@@ -10392,8 +10302,7 @@ int JSObject::GetLocalElementKeys(FixedArray* storage,
ASSERT(!storage || storage->length() >= counter);
break;
}
- case FAST_DOUBLE_ELEMENTS:
- case FAST_HOLEY_DOUBLE_ELEMENTS: {
+ case FAST_DOUBLE_ELEMENTS: {
int length = IsJSArray() ?
Smi::cast(JSArray::cast(this)->length())->value() :
FixedDoubleArray::cast(elements())->length();
@@ -11326,9 +11235,10 @@ MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) {
// Convert to fast elements.
Object* obj;
- MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(),
- FAST_HOLEY_ELEMENTS);
- if (!maybe_obj->ToObject(&obj)) return maybe_obj;
+ { MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(),
+ FAST_ELEMENTS);
+ if (!maybe_obj->ToObject(&obj)) return maybe_obj;
+ }
Map* new_map = Map::cast(obj);
PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED;
@@ -11339,9 +11249,9 @@ MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) {
}
FixedArray* fast_elements = FixedArray::cast(new_array);
dict->CopyValuesTo(fast_elements);
- ValidateElements();
- set_map_and_elements(new_map, fast_elements);
+ set_map(new_map);
+ set_elements(fast_elements);
} else if (HasExternalArrayElements()) {
// External arrays cannot have holes or undefined elements.
return Smi::FromInt(ExternalArray::cast(elements())->length());
@@ -11351,7 +11261,7 @@ MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) {
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
}
- ASSERT(HasFastSmiOrObjectElements() || HasFastDoubleElements());
+ ASSERT(HasFastTypeElements() || HasFastDoubleElements());
// Collect holes at the end, undefined before that and the rest at the
// start, and return the number of non-hole, non-undefined values.
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698