Commit f6875cee authored by mlippautz's avatar mlippautz Committed by Commit bot

Clear recorded slots when making a string external.

Slots in ConsString/SlicedString can point to an evacutaion candidate.
The MakeExternal function makes in-place conversion to external string.
After the conversion we can have a recorded slot containing an external
pointer. As long as the external pointer is aligned, this is not a
problem. We clear the recorded slots to fix verify-heap checks.

BUG=chromium:631969
LOG=NO

Finalizing CL: https://codereview.chromium.org/2199863002/

Review-Url: https://codereview.chromium.org/2242183003
Cr-Commit-Position: refs/heads/master@{#38653}
parent 619afa4b
......@@ -2155,6 +2155,7 @@ bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
Heap* heap = GetHeap();
bool is_one_byte = this->IsOneByteRepresentation();
bool is_internalized = this->IsInternalizedString();
bool has_pointers = this->IsConsString() || this->IsSlicedString();
// Morph the string to an external string by replacing the map and
// reinitializing the fields. This won't work if the space the existing
......@@ -2183,6 +2184,9 @@ bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
int new_size = this->SizeFromMap(new_map);
heap->CreateFillerObjectAt(this->address() + new_size, size - new_size,
ClearRecordedSlots::kNo);
if (has_pointers) {
heap->ClearRecordedSlotRange(this->address(), this->address() + new_size);
}
// We are storing the new map using release store after creating a filler for
// the left-over space to avoid races with the sweeper thread.
......@@ -2223,6 +2227,7 @@ bool String::MakeExternal(v8::String::ExternalOneByteStringResource* resource) {
if (size < ExternalString::kShortSize) return false;
Heap* heap = GetHeap();
bool is_internalized = this->IsInternalizedString();
bool has_pointers = this->IsConsString() || this->IsSlicedString();
// Morph the string to an external string by replacing the map and
// reinitializing the fields. This won't work if the space the existing
......@@ -2245,6 +2250,9 @@ bool String::MakeExternal(v8::String::ExternalOneByteStringResource* resource) {
int new_size = this->SizeFromMap(new_map);
heap->CreateFillerObjectAt(this->address() + new_size, size - new_size,
ClearRecordedSlots::kNo);
if (has_pointers) {
heap->ClearRecordedSlotRange(this->address(), this->address() + new_size);
}
// We are storing the new map using release store after creating a filler for
// the left-over space to avoid races with the sweeper thread.
......
......@@ -6818,6 +6818,65 @@ TEST(Regress615489) {
CHECK_LE(size_after, size_before);
}
class StaticOneByteResource : public v8::String::ExternalOneByteStringResource {
public:
explicit StaticOneByteResource(const char* data) : data_(data) {}
~StaticOneByteResource() {}
const char* data() const { return data_; }
size_t length() const { return strlen(data_); }
private:
const char* data_;
};
TEST(Regress631969) {
FLAG_manual_evacuation_candidates_selection = true;
FLAG_parallel_compaction = false;
FLAG_concurrent_sweeping = false;
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Heap* heap = CcTest::heap();
// Get the heap in clean state.
heap->CollectGarbage(OLD_SPACE);
heap->CollectGarbage(OLD_SPACE);
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
// Allocate two strings in a fresh page and mark the page as evacuation
// candidate.
heap::SimulateFullSpace(heap->old_space());
Handle<String> s1 = factory->NewStringFromStaticChars("123456789", TENURED);
Handle<String> s2 = factory->NewStringFromStaticChars("01234", TENURED);
Page::FromAddress(s1->address())
->SetFlag(MemoryChunk::FORCE_EVACUATION_CANDIDATE_FOR_TESTING);
heap::SimulateIncrementalMarking(heap, false);
// Allocate a cons string and promote it to a fresh page in the old space.
heap::SimulateFullSpace(heap->old_space());
Handle<String> s3;
factory->NewConsString(s1, s2).ToHandle(&s3);
heap->CollectGarbage(NEW_SPACE);
heap->CollectGarbage(NEW_SPACE);
// Finish incremental marking.
IncrementalMarking* marking = heap->incremental_marking();
while (!marking->IsComplete()) {
marking->Step(MB, i::IncrementalMarking::NO_GC_VIA_STACK_GUARD);
if (marking->IsReadyToOverApproximateWeakClosure()) {
marking->FinalizeIncrementally();
}
}
{
StaticOneByteResource external_string("12345678901234");
s3->MakeExternal(&external_string);
heap->CollectGarbage(OLD_SPACE);
}
}
TEST(LeftTrimFixedArrayInBlackArea) {
FLAG_black_allocation = true;
CcTest::InitializeVM();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment