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

Unified Diff: src/heap.cc

Issue 7860035: Merge bleeding edge up to 9192 into the GC branch. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/gc
Patch Set: Created 9 years, 3 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/heap.h ('k') | src/heap-inl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/heap.cc
diff --git a/src/heap.cc b/src/heap.cc
index 7503c0ad7369797c8eb46ca10789b693ac758a0c..36bbca5db6091c5358e6a639ee6bf23a588252fa 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -82,7 +82,7 @@ Heap::Heap()
reserved_semispace_size_(8 * Max(LUMP_OF_MEMORY, Page::kPageSize)),
max_semispace_size_(8 * Max(LUMP_OF_MEMORY, Page::kPageSize)),
initial_semispace_size_(Max(LUMP_OF_MEMORY, Page::kPageSize)),
- max_old_generation_size_(1024ul * LUMP_OF_MEMORY),
+ max_old_generation_size_(1400ul * LUMP_OF_MEMORY),
max_executable_size_(256l * LUMP_OF_MEMORY),
// Variables set based on semispace_size_ and old_generation_size_ in
@@ -825,6 +825,7 @@ void Heap::MarkCompactPrologue() {
isolate_->keyed_lookup_cache()->Clear();
isolate_->context_slot_cache()->Clear();
isolate_->descriptor_lookup_cache()->Clear();
+ StringSplitCache::Clear(string_split_cache());
isolate_->compilation_cache()->MarkCompactPrologue();
@@ -1347,6 +1348,10 @@ class ScavengingVisitor : public StaticVisitorBase {
&ObjectEvacuationStrategy<POINTER_OBJECT>::
template VisitSpecialized<ConsString::kSize>);
+ table_.Register(kVisitSlicedString,
+ &ObjectEvacuationStrategy<POINTER_OBJECT>::
+ template VisitSpecialized<SlicedString::kSize>);
+
table_.Register(kVisitSharedFunctionInfo,
&ObjectEvacuationStrategy<POINTER_OBJECT>::
template VisitSpecialized<SharedFunctionInfo::kSize>);
@@ -2296,6 +2301,13 @@ bool Heap::CreateInitialObjects() {
}
set_single_character_string_cache(FixedArray::cast(obj));
+ // Allocate cache for string split.
+ { MaybeObject* maybe_obj =
+ AllocateFixedArray(StringSplitCache::kStringSplitCacheSize, TENURED);
+ if (!maybe_obj->ToObject(&obj)) return false;
+ }
+ set_string_split_cache(FixedArray::cast(obj));
+
// Allocate cache for external strings pointing to native source code.
{ MaybeObject* maybe_obj = AllocateFixedArray(Natives::GetBuiltinsCount());
if (!maybe_obj->ToObject(&obj)) return false;
@@ -2321,6 +2333,75 @@ bool Heap::CreateInitialObjects() {
}
+Object* StringSplitCache::Lookup(
+ FixedArray* cache, String* string, String* pattern) {
+ if (!string->IsSymbol() || !pattern->IsSymbol()) return Smi::FromInt(0);
+ uint32_t hash = string->Hash();
+ uint32_t index = ((hash & (kStringSplitCacheSize - 1)) &
+ ~(kArrayEntriesPerCacheEntry - 1));
+ if (cache->get(index + kStringOffset) == string &&
+ cache->get(index + kPatternOffset) == pattern) {
+ return cache->get(index + kArrayOffset);
+ }
+ index = ((index + kArrayEntriesPerCacheEntry) & (kStringSplitCacheSize - 1));
+ if (cache->get(index + kStringOffset) == string &&
+ cache->get(index + kPatternOffset) == pattern) {
+ return cache->get(index + kArrayOffset);
+ }
+ return Smi::FromInt(0);
+}
+
+
+void StringSplitCache::Enter(Heap* heap,
+ FixedArray* cache,
+ String* string,
+ String* pattern,
+ FixedArray* array) {
+ if (!string->IsSymbol() || !pattern->IsSymbol()) return;
+ uint32_t hash = string->Hash();
+ uint32_t index = ((hash & (kStringSplitCacheSize - 1)) &
+ ~(kArrayEntriesPerCacheEntry - 1));
+ if (cache->get(index + kStringOffset) == Smi::FromInt(0)) {
+ cache->set(index + kStringOffset, string);
+ cache->set(index + kPatternOffset, pattern);
+ cache->set(index + kArrayOffset, array);
+ } else {
+ uint32_t index2 =
+ ((index + kArrayEntriesPerCacheEntry) & (kStringSplitCacheSize - 1));
+ if (cache->get(index2 + kStringOffset) == Smi::FromInt(0)) {
+ cache->set(index2 + kStringOffset, string);
+ cache->set(index2 + kPatternOffset, pattern);
+ cache->set(index2 + kArrayOffset, array);
+ } else {
+ cache->set(index2 + kStringOffset, Smi::FromInt(0));
+ cache->set(index2 + kPatternOffset, Smi::FromInt(0));
+ cache->set(index2 + kArrayOffset, Smi::FromInt(0));
+ cache->set(index + kStringOffset, string);
+ cache->set(index + kPatternOffset, pattern);
+ cache->set(index + kArrayOffset, array);
+ }
+ }
+ if (array->length() < 100) { // Limit how many new symbols we want to make.
+ for (int i = 0; i < array->length(); i++) {
+ String* str = String::cast(array->get(i));
+ Object* symbol;
+ MaybeObject* maybe_symbol = heap->LookupSymbol(str);
+ if (maybe_symbol->ToObject(&symbol)) {
+ array->set(i, symbol);
+ }
+ }
+ }
+ array->set_map(heap->fixed_cow_array_map());
+}
+
+
+void StringSplitCache::Clear(FixedArray* cache) {
+ for (int i = 0; i < kStringSplitCacheSize; i++) {
+ cache->set(i, Smi::FromInt(0));
+ }
+}
+
+
MaybeObject* Heap::InitializeNumberStringCache() {
// Compute the size of the number string cache based on the max heap size.
// max_semispace_size_ == 512 KB => number_string_cache_size = 32.
@@ -2641,6 +2722,8 @@ MaybeObject* Heap::AllocateConsString(String* first, String* second) {
// If the resulting string is small make a flat string.
if (length < String::kMinNonFlatLength) {
+ // Note that neither of the two inputs can be a slice because:
+ STATIC_ASSERT(String::kMinNonFlatLength <= SlicedString::kMinLength);
ASSERT(first->IsFlat());
ASSERT(second->IsFlat());
if (is_ascii) {
@@ -2732,24 +2815,69 @@ MaybeObject* Heap::AllocateSubString(String* buffer,
// Make an attempt to flatten the buffer to reduce access time.
buffer = buffer->TryFlattenGetString();
+ // TODO(1626): For now slicing external strings is not supported. However,
+ // a flat cons string can have an external string as first part in some cases.
+ // Therefore we have to single out this case as well.
+ if (!FLAG_string_slices ||
+ (buffer->IsConsString() &&
+ (!buffer->IsFlat() ||
+ !ConsString::cast(buffer)->first()->IsSeqString())) ||
+ buffer->IsExternalString() ||
+ length < SlicedString::kMinLength ||
+ pretenure == TENURED) {
+ Object* result;
+ { MaybeObject* maybe_result = buffer->IsAsciiRepresentation()
+ ? AllocateRawAsciiString(length, pretenure)
+ : AllocateRawTwoByteString(length, pretenure);
+ if (!maybe_result->ToObject(&result)) return maybe_result;
+ }
+ String* string_result = String::cast(result);
+ // Copy the characters into the new object.
+ if (buffer->IsAsciiRepresentation()) {
+ ASSERT(string_result->IsAsciiRepresentation());
+ char* dest = SeqAsciiString::cast(string_result)->GetChars();
+ String::WriteToFlat(buffer, dest, start, end);
+ } else {
+ ASSERT(string_result->IsTwoByteRepresentation());
+ uc16* dest = SeqTwoByteString::cast(string_result)->GetChars();
+ String::WriteToFlat(buffer, dest, start, end);
+ }
+ return result;
+ }
+
+ ASSERT(buffer->IsFlat());
+ ASSERT(!buffer->IsExternalString());
+#if DEBUG
+ buffer->StringVerify();
+#endif
+
Object* result;
- { MaybeObject* maybe_result = buffer->IsAsciiRepresentation()
- ? AllocateRawAsciiString(length, pretenure )
- : AllocateRawTwoByteString(length, pretenure);
+ { Map* map = buffer->IsAsciiRepresentation()
+ ? sliced_ascii_string_map()
+ : sliced_string_map();
+ MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
- String* string_result = String::cast(result);
- // Copy the characters into the new object.
- if (buffer->IsAsciiRepresentation()) {
- ASSERT(string_result->IsAsciiRepresentation());
- char* dest = SeqAsciiString::cast(string_result)->GetChars();
- String::WriteToFlat(buffer, dest, start, end);
+
+ AssertNoAllocation no_gc;
+ SlicedString* sliced_string = SlicedString::cast(result);
+ sliced_string->set_length(length);
+ sliced_string->set_hash_field(String::kEmptyHashField);
+ if (buffer->IsConsString()) {
+ ConsString* cons = ConsString::cast(buffer);
+ ASSERT(cons->second()->length() == 0);
+ sliced_string->set_parent(cons->first());
+ sliced_string->set_offset(start);
+ } else if (buffer->IsSlicedString()) {
+ // Prevent nesting sliced strings.
+ SlicedString* parent_slice = SlicedString::cast(buffer);
+ sliced_string->set_parent(parent_slice->parent());
+ sliced_string->set_offset(start + parent_slice->offset());
} else {
- ASSERT(string_result->IsTwoByteRepresentation());
- uc16* dest = SeqTwoByteString::cast(string_result)->GetChars();
- String::WriteToFlat(buffer, dest, start, end);
+ sliced_string->set_parent(buffer);
+ sliced_string->set_offset(start);
}
-
+ ASSERT(sliced_string->parent()->IsSeqString());
return result;
}
@@ -3572,6 +3700,9 @@ MaybeObject* Heap::ReinitializeJSGlobalProxy(JSFunction* constructor,
MaybeObject* Heap::AllocateStringFromAscii(Vector<const char> string,
PretenureFlag pretenure) {
+ if (string.length() == 1) {
+ return Heap::LookupSingleCharacterStringFromCode(string[0]);
+ }
Object* result;
{ MaybeObject* maybe_result =
AllocateRawAsciiString(string.length(), pretenure);
@@ -4111,10 +4242,9 @@ MaybeObject* Heap::AllocateBlockContext(JSFunction* function,
SerializedScopeInfo* scope_info) {
Object* result;
{ MaybeObject* maybe_result =
- AllocateFixedArray(scope_info->NumberOfContextSlots());
+ AllocateFixedArrayWithHoles(scope_info->NumberOfContextSlots());
if (!maybe_result->ToObject(&result)) return maybe_result;
}
- // TODO(keuchel): properly initialize context slots.
Context* context = reinterpret_cast<Context*>(result);
context->set_map(block_context_map());
context->set_closure(function);
« no previous file with comments | « src/heap.h ('k') | src/heap-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698