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

Unified Diff: src/objects.cc

Issue 10830005: In-place trimming of descriptor array when appending callbacks. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed comments. 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.h ('k') | no next file » | 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 65118437f14af1106f574d5ee7f704dbd0b0ae46..67ff486905d498889a93e64c14717fc0569604b5 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -2106,6 +2106,126 @@ void Map::LookupTransition(JSObject* holder,
}
+enum RightTrimMode { FROM_GC, FROM_MUTATOR };
+
+
+static void ZapEndOfFixedArray(Address new_end, int to_trim) {
+ // If we are doing a big trim in old space then we zap the space.
+ Object** zap = reinterpret_cast<Object**>(new_end);
+ for (int i = 1; i < to_trim; i++) {
+ *zap++ = Smi::FromInt(0);
+ }
+}
+
+template<RightTrimMode trim_mode>
+static void RightTrimFixedArray(Heap* heap, FixedArray* elms, int to_trim) {
+ ASSERT(elms->map() != HEAP->fixed_cow_array_map());
+ // For now this trick is only applied to fixed arrays in new and paged space.
+ // In large object space the object's start must coincide with chunk
+ // and thus the trick is just not applicable.
+ ASSERT(!HEAP->lo_space()->Contains(elms));
+
+ const int len = elms->length();
+
+ ASSERT(to_trim < len);
+
+ Address new_end = elms->address() + FixedArray::SizeFor(len - to_trim);
+
+ if (trim_mode == FROM_GC) {
+#ifdef DEBUG
+ ZapEndOfFixedArray(new_end, to_trim);
+#endif
+ } else {
+ ZapEndOfFixedArray(new_end, to_trim);
+ }
+
+ int size_delta = to_trim * kPointerSize;
+
+ // Technically in new space this write might be omitted (except for
+ // debug mode which iterates through the heap), but to play safer
+ // we still do it.
+ heap->CreateFillerObjectAt(new_end, size_delta);
+
+ elms->set_length(len - to_trim);
+
+ // Maintain marking consistency for IncrementalMarking.
+ if (Marking::IsBlack(Marking::MarkBitFrom(elms))) {
+ if (trim_mode == FROM_GC) {
+ MemoryChunk::IncrementLiveBytesFromGC(elms->address(), -size_delta);
+ } else {
+ MemoryChunk::IncrementLiveBytesFromMutator(elms->address(), -size_delta);
+ }
+ }
+}
+
+
+void Map::CopyAppendCallbackDescriptors(Handle<Map> map,
+ Handle<Object> descriptors) {
+ Isolate* isolate = map->GetIsolate();
+ Handle<DescriptorArray> array(map->instance_descriptors());
+ v8::NeanderArray callbacks(descriptors);
+ int nof_callbacks = callbacks.length();
+ int descriptor_count = array->number_of_descriptors();
+
+ // Ensure the keys are symbols before writing them into the instance
+ // descriptor. Since it may cause a GC, it has to be done before we
+ // temporarily put the heap in an invalid state while appending descriptors.
+ for (int i = 0; i < nof_callbacks; ++i) {
+ Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks.get(i)));
+ Handle<String> key =
+ isolate->factory()->SymbolFromString(
+ Handle<String>(String::cast(entry->name())));
+ entry->set_name(*key);
+ }
+
+ Handle<DescriptorArray> result =
+ isolate->factory()->NewDescriptorArray(descriptor_count + nof_callbacks);
+
+ // Ensure that marking will not progress and change color of objects.
+ DescriptorArray::WhitenessWitness witness(*result);
+
+ // Copy the descriptors from the array.
+ if (0 < descriptor_count) {
+ for (int i = 0; i < descriptor_count; i++) {
+ result->CopyFrom(i, *array, i, witness);
+ }
+ }
+
+ // After this point the GC is not allowed to run anymore until the map is in a
+ // consistent state again, i.e., all the descriptors are appended and the
+ // descriptor array is trimmed to the right size.
+ map->set_instance_descriptors(*result);
+
+ // Fill in new callback descriptors. Process the callbacks from
+ // back to front so that the last callback with a given name takes
+ // precedence over previously added callbacks with that name.
+ for (int i = nof_callbacks - 1; i >= 0; i--) {
+ AccessorInfo* entry = AccessorInfo::cast(callbacks.get(i));
+ String* key = String::cast(entry->name());
+ // Check if a descriptor with this name already exists before writing.
+ if (LinearSearch(*result, key, map->NumberOfSetDescriptors()) ==
+ DescriptorArray::kNotFound) {
+ CallbacksDescriptor desc(key, entry, entry->property_attributes());
+ map->AppendDescriptor(&desc, witness);
+ }
+ }
+
+ int new_number_of_descriptors = map->NumberOfSetDescriptors();
+ // Reinstall the original descriptor array if no new elements were added.
+ if (new_number_of_descriptors == descriptor_count) {
+ map->set_instance_descriptors(*array);
+ return;
+ }
+
+ // If duplicates were detected, trim the descriptor array to the right size.
+ int new_array_size = DescriptorArray::SizeFor(new_number_of_descriptors);
+ if (new_array_size < result->length()) {
+ RightTrimFixedArray<FROM_MUTATOR>(
+ isolate->heap(), *result, result->length() - new_array_size);
+ }
+}
+
+
static bool ContainsMap(MapHandleList* maps, Handle<Map> map) {
ASSERT(!map.is_null());
for (int i = 0; i < maps->length(); ++i) {
@@ -5723,10 +5843,9 @@ MaybeObject* DescriptorArray::Allocate(int number_of_descriptors,
return heap->empty_descriptor_array();
}
// Allocate the array of keys.
- { MaybeObject* maybe_array =
- heap->AllocateFixedArray(ToKeyIndex(number_of_descriptors));
- if (!maybe_array->To(&result)) return maybe_array;
- }
+ MaybeObject* maybe_array =
+ heap->AllocateFixedArray(SizeFor(number_of_descriptors));
+ if (!maybe_array->To(&result)) return maybe_array;
result->set(kEnumCacheIndex, Smi::FromInt(0));
result->set(kTransitionsIndex, Smi::FromInt(0));
@@ -7083,46 +7202,6 @@ void String::PrintOn(FILE* file) {
}
-// This function should only be called from within the GC, since it uses
-// IncrementLiveBytesFromGC. If called from anywhere else, this results in an
-// inconsistent live-bytes count.
-static void RightTrimFixedArray(Heap* heap, FixedArray* elms, int to_trim) {
- ASSERT(elms->map() != HEAP->fixed_cow_array_map());
- // For now this trick is only applied to fixed arrays in new and paged space.
- // In large object space the object's start must coincide with chunk
- // and thus the trick is just not applicable.
- ASSERT(!HEAP->lo_space()->Contains(elms));
-
- const int len = elms->length();
-
- ASSERT(to_trim < len);
-
- Address new_end = elms->address() + FixedArray::SizeFor(len - to_trim);
-
-#ifdef DEBUG
- // If we are doing a big trim in old space then we zap the space.
- Object** zap = reinterpret_cast<Object**>(new_end);
- for (int i = 1; i < to_trim; i++) {
- *zap++ = Smi::FromInt(0);
- }
-#endif
-
- int size_delta = to_trim * kPointerSize;
-
- // Technically in new space this write might be omitted (except for
- // debug mode which iterates through the heap), but to play safer
- // we still do it.
- heap->CreateFillerObjectAt(new_end, size_delta);
-
- elms->set_length(len - to_trim);
-
- // Maintain marking consistency for IncrementalMarking.
- if (Marking::IsBlack(Marking::MarkBitFrom(elms))) {
- MemoryChunk::IncrementLiveBytesFromGC(elms->address(), -size_delta);
- }
-}
-
-
// Clear a possible back pointer in case the transition leads to a dead map.
// Return true in case a back pointer has been cleared and false otherwise.
static bool ClearBackPointer(Heap* heap, Object* target) {
@@ -7185,7 +7264,8 @@ void Map::ClearNonLiveTransitions(Heap* heap) {
int trim = t->number_of_transitions() - transition_index;
if (trim > 0) {
- RightTrimFixedArray(heap, t, trim * TransitionArray::kTransitionSize);
+ RightTrimFixedArray<FROM_GC>(
+ heap, t, trim * TransitionArray::kTransitionSize);
}
}
« no previous file with comments | « src/objects.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698