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

Unified Diff: src/objects-inl.h

Issue 10697015: Separating transitions from descriptors. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Using WhitenessWitness in TransitionArray code. Created 8 years, 5 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-debug.cc ('k') | src/objects-printer.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/objects-inl.h
diff --git a/src/objects-inl.h b/src/objects-inl.h
index b33466977fa85fe60da724e23151e8d1441c61c4..360ba3f703b77226f78473b09f2d6c8f6d8391ce 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -47,6 +47,7 @@
#include "v8memory.h"
#include "factory.h"
#include "incremental-marking.h"
+#include "transitions-inl.h"
namespace v8 {
namespace internal {
@@ -524,6 +525,11 @@ bool Object::IsDescriptorArray() {
}
+bool Object::IsTransitionArray() {
+ return IsFixedArray();
+}
+
+
bool Object::IsDeoptimizationInputData() {
// Must be a fixed array.
if (!IsFixedArray()) return false;
@@ -1885,13 +1891,18 @@ bool DescriptorArray::MayContainTransitions() {
}
+bool DescriptorArray::HasTransitionArray() {
+ return MayContainTransitions() && !get(kTransitionsIndex)->IsSmi();
+}
+
+
int DescriptorArray::bit_field3_storage() {
Object* storage = READ_FIELD(this, kBitField3StorageOffset);
return Smi::cast(storage)->value();
}
void DescriptorArray::set_bit_field3_storage(int value) {
- ASSERT(this->MayContainTransitions());
+ ASSERT(length() > kBitField3StorageIndex);
WRITE_FIELD(this, kBitField3StorageOffset, Smi::FromInt(value));
}
@@ -1905,60 +1916,104 @@ void DescriptorArray::NoIncrementalWriteBarrierSwap(FixedArray* array,
}
-int DescriptorArray::Search(String* name) {
- SLOW_ASSERT(IsSortedNoDuplicates());
+// Perform a binary search in a fixed array. Low and high are entry indices. If
+// there are three entries in this array it should be called with low=0 and
+// high=2.
+template<typename T>
+int BinarySearch(T* array, String* name, int low, int high) {
+ uint32_t hash = name->Hash();
+ int limit = high;
+
+ ASSERT(low <= high);
+
+ while (low != high) {
+ int mid = (low + high) / 2;
+ String* mid_name = array->GetKey(mid);
+ uint32_t mid_hash = mid_name->Hash();
+
+ if (mid_hash >= hash) {
+ high = mid;
+ } else {
+ low = mid + 1;
+ }
+ }
+
+ for (; low <= limit && array->GetKey(low)->Hash() == hash; ++low) {
+ if (array->GetKey(low)->Equals(name)) return low;
+ }
+
+ return T::kNotFound;
+}
+
+
+// Perform a linear search in this fixed array. len is the number of entry
+// indices that are valid.
+template<typename T>
+int LinearSearch(T* array, SearchMode mode, String* name, int len) {
+ uint32_t hash = name->Hash();
+ for (int number = 0; number < len; number++) {
+ String* entry = array->GetKey(number);
+ uint32_t current_hash = entry->Hash();
+ if (mode == EXPECT_SORTED && current_hash > hash) break;
+ if (current_hash == hash && name->Equals(entry)) return number;
+ }
+ return T::kNotFound;
+}
+
+
+template<typename T>
+int Search(T* array, String* name) {
+ SLOW_ASSERT(array->IsSortedNoDuplicates());
// Check for empty descriptor array.
- int nof = number_of_descriptors();
- if (nof == 0) return kNotFound;
+ int nof = array->number_of_entries();
+ if (nof == 0) return T::kNotFound;
// Fast case: do linear search for small arrays.
const int kMaxElementsForLinearSearch = 8;
if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
- return LinearSearch(EXPECT_SORTED, name, nof);
+ return LinearSearch(array, EXPECT_SORTED, name, nof);
}
// Slow case: perform binary search.
- return BinarySearch(name, 0, nof - 1);
+ return BinarySearch(array, name, 0, nof - 1);
+}
+
+
+int DescriptorArray::Search(String* name) {
+ return internal::Search(this, name);
}
int DescriptorArray::SearchWithCache(String* name) {
- int number = GetIsolate()->descriptor_lookup_cache()->Lookup(this, name);
+ DescriptorLookupCache* cache = GetIsolate()->descriptor_lookup_cache();
+ int number = cache->Lookup(this, name);
if (number == DescriptorLookupCache::kAbsent) {
- number = Search(name);
- GetIsolate()->descriptor_lookup_cache()->Update(this, name, number);
+ number = internal::Search(this, name);
+ cache->Update(this, name, number);
}
return number;
}
-Map* DescriptorArray::elements_transition_map() {
- if (!this->MayContainTransitions()) {
- return NULL;
- }
- Object* transition_map = get(kTransitionsIndex);
- if (transition_map == Smi::FromInt(0)) {
- return NULL;
- } else {
- return Map::cast(transition_map);
- }
+TransitionArray* DescriptorArray::transitions() {
+ if (!this->MayContainTransitions()) return NULL;
+ Object* array = get(kTransitionsIndex);
+ return TransitionArray::cast(array);
}
-void DescriptorArray::set_elements_transition_map(
- Map* transition_map, WriteBarrierMode mode) {
- ASSERT(this->length() > kTransitionsIndex);
- Heap* heap = GetHeap();
- WRITE_FIELD(this, kTransitionsOffset, transition_map);
- CONDITIONAL_WRITE_BARRIER(
- heap, this, kTransitionsOffset, transition_map, mode);
- ASSERT(DescriptorArray::cast(this));
+void DescriptorArray::ClearTransitions() {
+ WRITE_FIELD(this, kTransitionsOffset, Smi::FromInt(0));
}
-void DescriptorArray::ClearElementsTransition() {
- WRITE_FIELD(this, kTransitionsOffset, Smi::FromInt(0));
+void DescriptorArray::set_transitions(TransitionArray* transitions_array,
+ WriteBarrierMode mode) {
+ Heap* heap = GetHeap();
+ WRITE_FIELD(this, kTransitionsOffset, transitions_array);
+ CONDITIONAL_WRITE_BARRIER(
+ heap, this, kTransitionsOffset, transitions_array, mode);
}
@@ -1976,17 +2031,6 @@ String* DescriptorArray::GetKey(int descriptor_number) {
}
-void DescriptorArray::SetKeyUnchecked(Heap* heap,
- int descriptor_number,
- String* key) {
- ASSERT(descriptor_number < number_of_descriptors());
- set_unchecked(heap,
- ToKeyIndex(descriptor_number),
- key,
- UPDATE_WRITE_BARRIER);
-}
-
-
Object** DescriptorArray::GetValueSlot(int descriptor_number) {
ASSERT(descriptor_number < number_of_descriptors());
return HeapObject::RawField(
@@ -2001,24 +2045,6 @@ Object* DescriptorArray::GetValue(int descriptor_number) {
}
-void DescriptorArray::SetNullValueUnchecked(Heap* heap, int descriptor_number) {
- ASSERT(descriptor_number < number_of_descriptors());
- set_null_unchecked(heap, ToValueIndex(descriptor_number));
-}
-
-
-
-void DescriptorArray::SetValueUnchecked(Heap* heap,
- int descriptor_number,
- Object* value) {
- ASSERT(descriptor_number < number_of_descriptors());
- set_unchecked(heap,
- ToValueIndex(descriptor_number),
- value,
- UPDATE_WRITE_BARRIER);
-}
-
-
PropertyDetails DescriptorArray::GetDetails(int descriptor_number) {
ASSERT(descriptor_number < number_of_descriptors());
Object* details = get(ToDetailsIndex(descriptor_number));
@@ -2026,12 +2052,6 @@ PropertyDetails DescriptorArray::GetDetails(int descriptor_number) {
}
-void DescriptorArray::SetDetailsUnchecked(int descriptor_number, Smi* value) {
- ASSERT(descriptor_number < number_of_descriptors());
- set_unchecked(ToDetailsIndex(descriptor_number), value);
-}
-
-
PropertyType DescriptorArray::GetType(int descriptor_number) {
return GetDetails(descriptor_number).type();
}
@@ -2060,38 +2080,6 @@ AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
}
-bool DescriptorArray::IsProperty(int descriptor_number) {
- Entry entry(this, descriptor_number);
- return IsPropertyDescriptor(&entry);
-}
-
-
-bool DescriptorArray::IsTransitionOnly(int descriptor_number) {
- switch (GetType(descriptor_number)) {
- case MAP_TRANSITION:
- case CONSTANT_TRANSITION:
- return true;
- case CALLBACKS: {
- Object* value = GetValue(descriptor_number);
- if (!value->IsAccessorPair()) return false;
- AccessorPair* accessors = AccessorPair::cast(value);
- return accessors->getter()->IsMap() && accessors->setter()->IsMap();
- }
- case NORMAL:
- case FIELD:
- case CONSTANT_FUNCTION:
- case HANDLER:
- case INTERCEPTOR:
- return false;
- case NONEXISTENT:
- UNREACHABLE();
- break;
- }
- UNREACHABLE(); // Keep the compiler happy.
- return false;
-}
-
-
void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
desc->Init(GetKey(descriptor_number),
GetValue(descriptor_number),
@@ -2129,16 +2117,14 @@ void DescriptorArray::NoIncrementalWriteBarrierSwapDescriptors(
}
-DescriptorArray::WhitenessWitness::WhitenessWitness(DescriptorArray* array)
+FixedArray::WhitenessWitness::WhitenessWitness(FixedArray* array)
: marking_(array->GetHeap()->incremental_marking()) {
marking_->EnterNoMarkingScope();
- if (array->number_of_descriptors() > 0) {
- ASSERT(Marking::Color(array) == Marking::WHITE_OBJECT);
- }
+ ASSERT(Marking::Color(array) == Marking::WHITE_OBJECT);
}
-DescriptorArray::WhitenessWitness::~WhitenessWitness() {
+FixedArray::WhitenessWitness::~WhitenessWitness() {
marking_->LeaveNoMarkingScope();
}
@@ -3431,12 +3417,8 @@ void Map::init_instance_descriptors() {
void Map::clear_instance_descriptors() {
- Object* object = READ_FIELD(this,
- kInstanceDescriptorsOrBitField3Offset);
+ Object* object = READ_FIELD(this, kInstanceDescriptorsOrBitField3Offset);
if (!object->IsSmi()) {
-#ifdef DEBUG
- ZapInstanceDescriptors();
-#endif
WRITE_FIELD(
this,
kInstanceDescriptorsOrBitField3Offset,
@@ -3462,11 +3444,6 @@ void Map::set_instance_descriptors(DescriptorArray* value,
}
}
ASSERT(!is_shared());
-#ifdef DEBUG
- if (value != instance_descriptors()) {
- ZapInstanceDescriptors();
- }
-#endif
WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, value);
CONDITIONAL_WRITE_BARRIER(
heap, this, kInstanceDescriptorsOrBitField3Offset, value, mode);
@@ -3489,7 +3466,7 @@ void Map::ClearDescriptorArray() {
#ifdef DEBUG
Object* object = READ_FIELD(this, kInstanceDescriptorsOrBitField3Offset);
if (!object->IsSmi()) {
- ZapInstanceDescriptors();
+ ZapTransitions();
}
#endif
WRITE_FIELD(this,
@@ -3521,13 +3498,93 @@ Object* Map::GetBackPointer() {
}
+bool Map::HasElementsTransition() {
+ return HasTransitionArray() && transitions()->HasElementsTransition();
+}
+
+
+bool Map::HasTransitionArray() {
+ return instance_descriptors()->HasTransitionArray();
+}
+
+
Map* Map::elements_transition_map() {
- return instance_descriptors()->elements_transition_map();
+ return transitions()->elements_transition();
}
-void Map::set_elements_transition_map(Map* transitioned_map) {
- return instance_descriptors()->set_elements_transition_map(transitioned_map);
+MaybeObject* Map::AddTransition(String* key, Object* value) {
+ if (HasTransitionArray()) return transitions()->CopyInsert(key, value);
+ return TransitionArray::NewWith(key, value);
+}
+
+
+// If the map does not have a descriptor array, install a new empty
+// descriptor array that has room for a transition array.
+static MaybeObject* AllowTransitions(Map* map) {
+ if (map->instance_descriptors()->MayContainTransitions()) return map;
+ DescriptorArray* descriptors;
+ MaybeObject* maybe_descriptors =
+ DescriptorArray::Allocate(0, DescriptorArray::CANNOT_BE_SHARED);
+ if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors;
+ map->set_instance_descriptors(descriptors);
+ return descriptors;
+}
+
+
+// If the descriptor does not have a transition array, install a new
+// transition array that has room for an element transition.
+static MaybeObject* AllowElementsTransition(Map* map) {
+ if (map->HasTransitionArray()) return map;
+
+ AllowTransitions(map);
+
+ TransitionArray* transitions;
+ MaybeObject* maybe_transitions = TransitionArray::Allocate(0);
+ if (!maybe_transitions->To(&transitions)) return maybe_transitions;
+ MaybeObject* added_transitions = map->set_transitions(transitions);
+ if (added_transitions->IsFailure()) return added_transitions;
+ return transitions;
+}
+
+
+MaybeObject* Map::set_elements_transition_map(Map* transitioned_map) {
+ MaybeObject* allow_elements = AllowElementsTransition(this);
+ if (allow_elements->IsFailure()) return allow_elements;
+ transitions()->set_elements_transition(transitioned_map);
+ return this;
+}
+
+
+TransitionArray* Map::transitions() {
+ return instance_descriptors()->transitions();
+}
+
+
+void Map::ClearTransitions() {
+#ifdef DEBUG
+ ZapTransitions();
+#endif
+ DescriptorArray* descriptors = instance_descriptors();
+ if (descriptors->number_of_descriptors() == 0) {
+ ClearDescriptorArray();
+ } else {
+ descriptors->ClearTransitions();
+ }
+}
+
+
+MaybeObject* Map::set_transitions(TransitionArray* transitions_array) {
+ MaybeObject* allow_transitions = AllowTransitions(this);
+ if (allow_transitions->IsFailure()) return allow_transitions;
+#ifdef DEBUG
+ if (HasTransitionArray()) {
+ ASSERT(transitions() != transitions_array);
+ ZapTransitions();
+ }
+#endif
+ instance_descriptors()->set_transitions(transitions_array);
+ return this;
}
« no previous file with comments | « src/objects-debug.cc ('k') | src/objects-printer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698