[heap] Avoid the use of cells to point from code to new-space objects.

Cells were needed originally because there was no typed remembered set to
record direct pointers from code space to new space. A previous
CL (https://codereview.chromium.org/2003553002/) already introduced
the remembered set, this CL uses it.

This CL
* stores direct pointers in code objects, even if the target is in new space,
* records the slot of the pointer in typed-old-to-new remembered set,
* adds a list which stores weak code-to-new-space references,
* adds a test to test-heap.cc for weak code-to-new-space references,
* removes prints in tail-call-megatest.js

R=ulan@chromium.org

Review-Url: https://codereview.chromium.org/2045263002
Cr-Commit-Position: refs/heads/master@{#37134}
This commit is contained in:
ahaas 2016-06-21 03:40:14 -07:00 committed by Commit bot
parent 5e0cd389bf
commit 2d2087b79a
30 changed files with 270 additions and 162 deletions

View File

@ -138,6 +138,7 @@ void RelocInfo::set_target_object(Object* target,
target->IsHeapObject()) {
host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
host(), this, HeapObject::cast(target));
host()->GetHeap()->RecordWriteIntoCode(host(), this, target);
}
}

View File

@ -275,7 +275,6 @@ Operand::Operand(Handle<Object> handle) {
// Verify all Objects referred by code are NOT in new space.
Object* obj = *handle;
if (obj->IsHeapObject()) {
DCHECK(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj));
imm32_ = reinterpret_cast<intptr_t>(handle.location());
rmode_ = RelocInfo::EMBEDDED_OBJECT;
} else {

View File

@ -240,18 +240,11 @@ void MacroAssembler::Push(Handle<Object> handle) {
void MacroAssembler::Move(Register dst, Handle<Object> value) {
AllowDeferredHandleDereference smi_check;
if (value->IsSmi()) {
mov(dst, Operand(value));
} else {
DCHECK(value->IsHeapObject());
if (isolate()->heap()->InNewSpace(*value)) {
Handle<Cell> cell = isolate()->factory()->NewCell(value);
mov(dst, Operand(cell));
ldr(dst, FieldMemOperand(dst, Cell::kValueOffset));
} else {
mov(dst, Operand(value));
}
mov(dst, Operand(value));
}
}

View File

@ -731,6 +731,7 @@ void RelocInfo::set_target_object(Object* target,
target->IsHeapObject()) {
host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
host(), this, HeapObject::cast(target));
host()->GetHeap()->RecordWriteIntoCode(host(), this, target);
}
}

View File

@ -280,7 +280,6 @@ void Immediate::InitializeHandle(Handle<Object> handle) {
// Verify all Objects referred by code are NOT in new space.
Object* obj = *handle;
if (obj->IsHeapObject()) {
DCHECK(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj));
value_ = reinterpret_cast<intptr_t>(handle.location());
rmode_ = RelocInfo::EMBEDDED_OBJECT;
} else {

View File

@ -1425,14 +1425,7 @@ void MacroAssembler::LoadTrueFalseRoots(Register true_root,
void MacroAssembler::LoadHeapObject(Register result,
Handle<HeapObject> object) {
AllowDeferredHandleDereference using_raw_address;
if (isolate()->heap()->InNewSpace(*object)) {
Handle<Cell> cell = isolate()->factory()->NewCell(object);
Mov(result, Operand(cell));
Ldr(result, FieldMemOperand(result, Cell::kValueOffset));
} else {
Mov(result, Operand(object));
}
Mov(result, Operand(object));
}

View File

@ -284,9 +284,14 @@ void AddWeakObjectToCodeDependency(Isolate* isolate, Handle<HeapObject> object,
Handle<Code> code) {
Handle<WeakCell> cell = Code::WeakCellFor(code);
Heap* heap = isolate->heap();
Handle<DependentCode> dep(heap->LookupWeakObjectToCodeDependency(object));
dep = DependentCode::InsertWeakCode(dep, DependentCode::kWeakCodeGroup, cell);
heap->AddWeakObjectToCodeDependency(object, dep);
if (heap->InNewSpace(*object)) {
heap->AddWeakNewSpaceObjectToCodeDependency(object, cell);
} else {
Handle<DependentCode> dep(heap->LookupWeakObjectToCodeDependency(object));
dep =
DependentCode::InsertWeakCode(dep, DependentCode::kWeakCodeGroup, cell);
heap->AddWeakObjectToCodeDependency(object, dep);
}
}
} // namespace

View File

@ -426,6 +426,12 @@ void Heap::RecordWrite(Object* object, int offset, Object* o) {
HeapObject::cast(object)->address() + offset);
}
void Heap::RecordWriteIntoCode(Code* host, RelocInfo* rinfo, Object* value) {
if (InNewSpace(value)) {
RecordWriteIntoCodeSlow(host, rinfo, value);
}
}
void Heap::RecordFixedArrayElements(FixedArray* array, int offset, int length) {
if (InNewSpace(array)) return;
Page* page = Page::FromAddress(reinterpret_cast<Address>(array));

View File

@ -1469,38 +1469,6 @@ void Heap::MarkCompactPrologue() {
}
#ifdef VERIFY_HEAP
// Visitor class to verify pointers in code or data space do not point into
// new space.
class VerifyNonPointerSpacePointersVisitor : public ObjectVisitor {
public:
explicit VerifyNonPointerSpacePointersVisitor(Heap* heap) : heap_(heap) {}
void VisitPointers(Object** start, Object** end) override {
for (Object** current = start; current < end; current++) {
if ((*current)->IsHeapObject()) {
CHECK(!heap_->InNewSpace(HeapObject::cast(*current)));
}
}
}
private:
Heap* heap_;
};
static void VerifyNonPointerSpacePointers(Heap* heap) {
// Verify that there are no pointers to new space in spaces where we
// do not expect them.
VerifyNonPointerSpacePointersVisitor v(heap);
HeapObjectIterator code_it(heap->code_space());
for (HeapObject* object = code_it.Next(); object != NULL;
object = code_it.Next())
object->Iterate(&v);
}
#endif // VERIFY_HEAP
void Heap::CheckNewSpaceExpansionCriteria() {
if (FLAG_experimental_new_space_growth_heuristic) {
if (new_space_.TotalCapacity() < new_space_.MaximumCapacity() &&
@ -1613,10 +1581,6 @@ void Heap::Scavenge() {
mark_compact_collector()->sweeper().EnsureNewSpaceCompleted();
#ifdef VERIFY_HEAP
if (FLAG_verify_heap) VerifyNonPointerSpacePointers(this);
#endif
gc_state_ = SCAVENGE;
// Implements Cheney's copying algorithm
@ -2859,6 +2823,10 @@ void Heap::CreateInitialObjects() {
*WeakHashTable::New(isolate(), 16, USE_DEFAULT_MINIMUM_CAPACITY,
TENURED));
set_weak_new_space_object_to_code_list(
ArrayList::cast(*(factory->NewFixedArray(16, TENURED))));
weak_new_space_object_to_code_list()->SetLength(0);
set_script_list(Smi::FromInt(0));
Handle<SeededNumberDictionary> slow_element_dictionary =
@ -2918,7 +2886,6 @@ void Heap::CreateInitialObjects() {
CreateFixedStubs();
}
bool Heap::RootCanBeWrittenAfterInitialization(Heap::RootListIndex root_index) {
switch (root_index) {
case kNumberStringCacheRootIndex:
@ -2933,6 +2900,7 @@ bool Heap::RootCanBeWrittenAfterInitialization(Heap::RootListIndex root_index) {
case kMicrotaskQueueRootIndex:
case kDetachedContextsRootIndex:
case kWeakObjectToCodeTableRootIndex:
case kWeakNewSpaceObjectToCodeListRootIndex:
case kRetainedMapsRootIndex:
case kNoScriptSharedFunctionInfosRootIndex:
case kWeakStackTraceListRootIndex:
@ -5563,6 +5531,18 @@ void Heap::RemoveGCEpilogueCallback(v8::Isolate::GCCallback callback) {
UNREACHABLE();
}
// TODO(ishell): Find a better place for this.
void Heap::AddWeakNewSpaceObjectToCodeDependency(Handle<HeapObject> obj,
Handle<WeakCell> code) {
DCHECK(InNewSpace(*obj));
DCHECK(!InNewSpace(*code));
Handle<ArrayList> list(weak_new_space_object_to_code_list(), isolate());
list = ArrayList::Add(list, isolate()->factory()->NewWeakCell(obj), code);
if (*list != weak_new_space_object_to_code_list()) {
set_weak_new_space_object_to_code_list(*list);
}
}
// TODO(ishell): Find a better place for this.
void Heap::AddWeakObjectToCodeDependency(Handle<HeapObject> obj,
Handle<DependentCode> dep) {
@ -5710,6 +5690,26 @@ void Heap::ClearRecordedSlotRange(Address start, Address end) {
}
}
void Heap::RecordWriteIntoCodeSlow(Code* host, RelocInfo* rinfo,
Object* value) {
DCHECK(InNewSpace(value));
Page* source_page = Page::FromAddress(reinterpret_cast<Address>(host));
RelocInfo::Mode rmode = rinfo->rmode();
Address addr = rinfo->pc();
SlotType slot_type = SlotTypeForRelocInfoMode(rmode);
if (rinfo->IsInConstantPool()) {
addr = rinfo->constant_pool_entry_address();
if (RelocInfo::IsCodeTarget(rmode)) {
slot_type = CODE_ENTRY_SLOT;
} else {
DCHECK(RelocInfo::IsEmbeddedObject(rmode));
slot_type = OBJECT_SLOT;
}
}
RememberedSet<OLD_TO_NEW>::InsertTyped(
source_page, reinterpret_cast<Address>(host), slot_type, addr);
}
Space* AllSpaces::next() {
switch (counter_++) {
case NEW_SPACE:

View File

@ -189,6 +189,11 @@ using v8::MemoryPressureLevel;
V(FixedArray, detached_contexts, DetachedContexts) \
V(ArrayList, retained_maps, RetainedMaps) \
V(WeakHashTable, weak_object_to_code_table, WeakObjectToCodeTable) \
/* weak_new_space_object_to_code_list is an array of weak cells, where */ \
/* slots with even indices refer to the weak object, and the subsequent */ \
/* slots refer to the code with the reference to the weak object. */ \
V(ArrayList, weak_new_space_object_to_code_list, \
WeakNewSpaceObjectToCodeList) \
V(PropertyCell, array_protector, ArrayProtector) \
V(Cell, is_concat_spreadable_protector, IsConcatSpreadableProtector) \
V(PropertyCell, empty_property_cell, EmptyPropertyCell) \
@ -839,6 +844,9 @@ class Heap {
return new_space_.IsAtMaximumCapacity() && maximum_size_scavenges_ == 0;
}
void AddWeakNewSpaceObjectToCodeDependency(Handle<HeapObject> obj,
Handle<WeakCell> code);
void AddWeakObjectToCodeDependency(Handle<HeapObject> obj,
Handle<DependentCode> dep);
@ -1099,6 +1107,8 @@ class Heap {
// Write barrier support for object[offset] = o;
inline void RecordWrite(Object* object, int offset, Object* o);
inline void RecordWriteIntoCode(Code* host, RelocInfo* rinfo, Object* target);
void RecordWriteIntoCodeSlow(Code* host, RelocInfo* rinfo, Object* target);
inline void RecordFixedArrayElements(FixedArray* array, int offset,
int length);

View File

@ -1615,6 +1615,9 @@ class RecordMigratedSlotVisitor final : public ObjectVisitor {
DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode()));
Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
Code* host = rinfo->host();
// The target is always in old space, we don't have to record the slot in
// the old-to-new remembered set.
DCHECK(!collector_->heap()->InNewSpace(target));
collector_->RecordRelocSlot(host, rinfo, target);
}
@ -1623,6 +1626,9 @@ class RecordMigratedSlotVisitor final : public ObjectVisitor {
rinfo->IsPatchedDebugBreakSlotSequence());
Code* target = Code::GetCodeFromTargetAddress(rinfo->debug_call_address());
Code* host = rinfo->host();
// The target is always in old space, we don't have to record the slot in
// the old-to-new remembered set.
DCHECK(!collector_->heap()->InNewSpace(target));
collector_->RecordRelocSlot(host, rinfo, target);
}
@ -1630,6 +1636,7 @@ class RecordMigratedSlotVisitor final : public ObjectVisitor {
DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
HeapObject* object = HeapObject::cast(rinfo->target_object());
Code* host = rinfo->host();
collector_->heap()->RecordWriteIntoCode(host, rinfo, object);
collector_->RecordRelocSlot(host, rinfo, object);
}
@ -1637,6 +1644,9 @@ class RecordMigratedSlotVisitor final : public ObjectVisitor {
DCHECK(rinfo->rmode() == RelocInfo::CELL);
Cell* cell = rinfo->target_cell();
Code* host = rinfo->host();
// The cell is always in old space, we don't have to record the slot in
// the old-to-new remembered set.
DCHECK(!collector_->heap()->InNewSpace(cell));
collector_->RecordRelocSlot(host, rinfo, cell);
}
@ -2506,6 +2516,35 @@ void MarkCompactCollector::MarkDependentCodeForDeoptimization(
current = current->next_link();
}
{
ArrayList* list = heap_->weak_new_space_object_to_code_list();
int counter = 0;
for (int i = 0; i < list->Length(); i += 2) {
WeakCell* obj = WeakCell::cast(list->Get(i));
WeakCell* dep = WeakCell::cast(list->Get(i + 1));
if (obj->cleared() || dep->cleared()) {
if (!dep->cleared()) {
Code* code = Code::cast(dep->value());
if (!code->marked_for_deoptimization()) {
DependentCode::SetMarkedForDeoptimization(
code, DependentCode::DependencyGroup::kWeakCodeGroup);
code->InvalidateEmbeddedObjects();
have_code_to_deoptimize_ = true;
}
}
} else {
// We record the slot manually because marking is finished at this
// point and the write barrier would bailout.
list->Set(counter, obj, SKIP_WRITE_BARRIER);
RecordSlot(list, list->Slot(counter), obj);
counter++;
list->Set(counter, dep, SKIP_WRITE_BARRIER);
RecordSlot(list, list->Slot(counter), dep);
counter++;
}
}
}
WeakHashTable* table = heap_->weak_object_to_code_table();
uint32_t capacity = table->Capacity();
for (uint32_t i = 0; i < capacity; i++) {
@ -2850,30 +2889,16 @@ void MarkCompactCollector::AbortTransitionArrays() {
heap()->set_encountered_transition_arrays(Smi::FromInt(0));
}
static inline SlotType SlotTypeForRMode(RelocInfo::Mode rmode) {
if (RelocInfo::IsCodeTarget(rmode)) {
return CODE_TARGET_SLOT;
} else if (RelocInfo::IsCell(rmode)) {
return CELL_TARGET_SLOT;
} else if (RelocInfo::IsEmbeddedObject(rmode)) {
return EMBEDDED_OBJECT_SLOT;
} else if (RelocInfo::IsDebugBreakSlot(rmode)) {
return DEBUG_TARGET_SLOT;
}
UNREACHABLE();
return NUMBER_OF_SLOT_TYPES;
}
void MarkCompactCollector::RecordRelocSlot(Code* host, RelocInfo* rinfo,
Object* target) {
Page* target_page = Page::FromAddress(reinterpret_cast<Address>(target));
Page* source_page = Page::FromAddress(reinterpret_cast<Address>(host));
RelocInfo::Mode rmode = rinfo->rmode();
if (target_page->IsEvacuationCandidate() &&
(rinfo->host() == NULL ||
!ShouldSkipEvacuationSlotRecording(rinfo->host()))) {
RelocInfo::Mode rmode = rinfo->rmode();
Address addr = rinfo->pc();
SlotType slot_type = SlotTypeForRMode(rmode);
SlotType slot_type = SlotTypeForRelocInfoMode(rmode);
if (rinfo->IsInConstantPool()) {
addr = rinfo->constant_pool_entry_address();
if (RelocInfo::IsCodeTarget(rmode)) {
@ -3498,6 +3523,12 @@ int MarkCompactCollector::Sweeper::RawSweep(PagedSpace* space, Page* p,
}
void MarkCompactCollector::InvalidateCode(Code* code) {
Page* page = Page::FromAddress(code->address());
Address start = code->instruction_start();
Address end = code->address() + code->Size();
RememberedSet<OLD_TO_NEW>::RemoveRangeTyped(page, start, end);
if (heap_->incremental_marking()->IsCompacting() &&
!ShouldSkipEvacuationSlotRecording(code)) {
DCHECK(compacting_);
@ -3509,11 +3540,7 @@ void MarkCompactCollector::InvalidateCode(Code* code) {
// Ignore all slots that might have been recorded in the body of the
// deoptimized code object. Assumption: no slots will be recorded for
// this object after invalidating it.
Page* page = Page::FromAddress(code->address());
Address start = code->instruction_start();
Address end = code->address() + code->Size();
RememberedSet<OLD_TO_OLD>::RemoveRangeTyped(page, start, end);
RememberedSet<OLD_TO_NEW>::RemoveRangeTyped(page, start, end);
}
}
@ -4117,6 +4144,9 @@ void MarkCompactCollector::RecordCodeTargetPatch(Address pc, Code* target) {
MarkBit mark_bit = Marking::MarkBitFrom(host);
if (Marking::IsBlack(mark_bit)) {
RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host);
// The target is always in old space, we don't have to record the slot in
// the old-to-new remembered set.
DCHECK(!heap()->InNewSpace(target));
RecordRelocSlot(host, &rinfo, target);
}
}

View File

@ -9,6 +9,7 @@
#include "src/heap/slot-set.h"
#include "src/heap/spaces.h"
#include "src/heap/store-buffer.h"
#include "src/macro-assembler.h"
namespace v8 {
namespace internal {
@ -16,16 +17,38 @@ namespace internal {
template <PointerDirection direction>
void RememberedSet<direction>::ClearInvalidSlots(Heap* heap) {
STATIC_ASSERT(direction == OLD_TO_NEW);
PageIterator it(heap->old_space());
MemoryChunk* chunk;
while (it.has_next()) {
chunk = it.next();
SlotSet* slots = GetSlotSet(chunk);
if (slots != nullptr) {
slots->Iterate([heap, chunk](Address addr) {
Object** slot = reinterpret_cast<Object**>(addr);
return IsValidSlot(heap, chunk, slot) ? KEEP_SLOT : REMOVE_SLOT;
});
{
PageIterator it(heap->old_space());
MemoryChunk* chunk;
while (it.has_next()) {
chunk = it.next();
{
SlotSet* slots = GetSlotSet(chunk);
if (slots != nullptr) {
slots->Iterate([heap, chunk](Address addr) {
Object** slot = reinterpret_cast<Object**>(addr);
return IsValidSlot(heap, chunk, slot) ? KEEP_SLOT : REMOVE_SLOT;
});
}
}
}
}
{
PageIterator it(heap->code_space());
MemoryChunk* chunk;
while (it.has_next()) {
chunk = it.next();
TypedSlotSet* slots = GetTypedSlotSet(chunk);
if (slots != nullptr) {
slots->Iterate(
[heap, chunk](SlotType type, Address host_addr, Address addr) {
if (Marking::IsBlack(Marking::MarkBitFrom(host_addr))) {
return KEEP_SLOT;
} else {
return REMOVE_SLOT;
}
});
}
}
}
}

View File

@ -345,6 +345,20 @@ class UpdateTypedSlotHelper {
}
};
inline SlotType SlotTypeForRelocInfoMode(RelocInfo::Mode rmode) {
if (RelocInfo::IsCodeTarget(rmode)) {
return CODE_TARGET_SLOT;
} else if (RelocInfo::IsCell(rmode)) {
return CELL_TARGET_SLOT;
} else if (RelocInfo::IsEmbeddedObject(rmode)) {
return EMBEDDED_OBJECT_SLOT;
} else if (RelocInfo::IsDebugBreakSlot(rmode)) {
return DEBUG_TARGET_SLOT;
}
UNREACHABLE();
return NUMBER_OF_SLOT_TYPES;
}
} // namespace internal
} // namespace v8

View File

@ -137,8 +137,7 @@ void RelocInfo::set_target_object(Object* target,
if (write_barrier_mode == UPDATE_WRITE_BARRIER &&
host() != NULL &&
target->IsHeapObject()) {
host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
host(), this, HeapObject::cast(target));
host()->GetHeap()->RecordWriteIntoCode(host(), this, target);
}
}
@ -341,7 +340,6 @@ Immediate::Immediate(Handle<Object> handle) {
// Verify all Objects referred by code are NOT in new space.
Object* obj = *handle;
if (obj->IsHeapObject()) {
DCHECK(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj));
x_ = reinterpret_cast<intptr_t>(handle.location());
rmode_ = RelocInfo::EMBEDDED_OBJECT;
} else {
@ -380,7 +378,6 @@ void Assembler::emit(Handle<Object> handle) {
AllowDeferredHandleDereference heap_object_check;
// Verify all Objects referred by code are NOT in new space.
Object* obj = *handle;
DCHECK(!isolate()->heap()->InNewSpace(obj));
if (obj->IsHeapObject()) {
emit(reinterpret_cast<intptr_t>(handle.location()),
RelocInfo::EMBEDDED_OBJECT);

View File

@ -2595,37 +2595,15 @@ int MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
void MacroAssembler::LoadHeapObject(Register result,
Handle<HeapObject> object) {
AllowDeferredHandleDereference embedding_raw_address;
if (isolate()->heap()->InNewSpace(*object)) {
Handle<Cell> cell = isolate()->factory()->NewCell(object);
mov(result, Operand::ForCell(cell));
} else {
mov(result, object);
}
mov(result, object);
}
void MacroAssembler::CmpHeapObject(Register reg, Handle<HeapObject> object) {
AllowDeferredHandleDereference using_raw_address;
if (isolate()->heap()->InNewSpace(*object)) {
Handle<Cell> cell = isolate()->factory()->NewCell(object);
cmp(reg, Operand::ForCell(cell));
} else {
cmp(reg, object);
}
}
void MacroAssembler::PushHeapObject(Handle<HeapObject> object) {
AllowDeferredHandleDereference using_raw_address;
if (isolate()->heap()->InNewSpace(*object)) {
Handle<Cell> cell = isolate()->factory()->NewCell(object);
push(Operand::ForCell(cell));
} else {
Push(object);
}
cmp(reg, object);
}
void MacroAssembler::PushHeapObject(Handle<HeapObject> object) { Push(object); }
void MacroAssembler::CmpWeakValue(Register value, Handle<WeakCell> cell,
Register scratch) {

View File

@ -225,6 +225,7 @@ void RelocInfo::set_target_object(Object* target,
target->IsHeapObject()) {
host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
host(), this, HeapObject::cast(target));
host()->GetHeap()->RecordWriteIntoCode(host(), this, target);
}
}

View File

@ -225,7 +225,6 @@ Operand::Operand(Handle<Object> handle) {
// Verify all Objects referred by code are NOT in new space.
Object* obj = *handle;
if (obj->IsHeapObject()) {
DCHECK(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj));
imm32_ = reinterpret_cast<intptr_t>(handle.location());
rmode_ = RelocInfo::EMBEDDED_OBJECT;
} else {

View File

@ -1403,18 +1403,11 @@ void MacroAssembler::Usdc1(FPURegister fd, const MemOperand& rs,
void MacroAssembler::li(Register dst, Handle<Object> value, LiFlags mode) {
AllowDeferredHandleDereference smi_check;
if (value->IsSmi()) {
li(dst, Operand(value), mode);
} else {
DCHECK(value->IsHeapObject());
if (isolate()->heap()->InNewSpace(*value)) {
Handle<Cell> cell = isolate()->factory()->NewCell(value);
li(dst, Operand(cell));
lw(dst, FieldMemOperand(dst, Cell::kValueOffset));
} else {
li(dst, Operand(value));
}
li(dst, Operand(value));
}
}

View File

@ -213,6 +213,7 @@ void RelocInfo::set_target_object(Object* target,
target->IsHeapObject()) {
host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
host(), this, HeapObject::cast(target));
host()->GetHeap()->RecordWriteIntoCode(host(), this, target);
}
}

View File

@ -204,7 +204,6 @@ Operand::Operand(Handle<Object> handle) {
// Verify all Objects referred by code are NOT in new space.
Object* obj = *handle;
if (obj->IsHeapObject()) {
DCHECK(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj));
imm64_ = reinterpret_cast<intptr_t>(handle.location());
rmode_ = RelocInfo::EMBEDDED_OBJECT;
} else {

View File

@ -1597,18 +1597,11 @@ void MacroAssembler::Usdc1(FPURegister fd, const MemOperand& rs,
}
void MacroAssembler::li(Register dst, Handle<Object> value, LiFlags mode) {
AllowDeferredHandleDereference smi_check;
if (value->IsSmi()) {
li(dst, Operand(value), mode);
} else {
DCHECK(value->IsHeapObject());
if (isolate()->heap()->InNewSpace(*value)) {
Handle<Cell> cell = isolate()->factory()->NewCell(value);
li(dst, Operand(cell));
ld(dst, FieldMemOperand(dst, Cell::kValueOffset));
} else {
li(dst, Operand(value));
}
li(dst, Operand(value));
}
}

View File

@ -701,11 +701,25 @@ void Code::VerifyEmbeddedObjectsDependency() {
CHECK(map->dependent_code()->Contains(DependentCode::kWeakCodeGroup,
cell));
} else if (obj->IsJSObject()) {
WeakHashTable* table =
GetIsolate()->heap()->weak_object_to_code_table();
Handle<HeapObject> key_obj(HeapObject::cast(obj), isolate);
CHECK(DependentCode::cast(table->Lookup(key_obj))
->Contains(DependentCode::kWeakCodeGroup, cell));
if (isolate->heap()->InNewSpace(obj)) {
ArrayList* list =
GetIsolate()->heap()->weak_new_space_object_to_code_list();
bool found = false;
for (int i = 0; i < list->Length(); i += 2) {
WeakCell* obj_cell = WeakCell::cast(list->Get(i));
if (!obj_cell->cleared() && obj_cell->value() == obj &&
WeakCell::cast(list->Get(i + 1)) == cell) {
found = true;
break;
}
}
CHECK(found);
} else {
Handle<HeapObject> key_obj(HeapObject::cast(obj), isolate);
DependentCode* dep =
GetIsolate()->heap()->LookupWeakObjectToCodeDependency(key_obj);
dep->Contains(DependentCode::kWeakCodeGroup, cell);
}
}
}
}

View File

@ -2464,9 +2464,8 @@ Object** ArrayList::Slot(int index) {
return data_start() + kFirstIndex + index;
}
void ArrayList::Set(int index, Object* obj) {
FixedArray::cast(this)->set(kFirstIndex + index, obj);
void ArrayList::Set(int index, Object* obj, WriteBarrierMode mode) {
FixedArray::cast(this)->set(kFirstIndex + index, obj, mode);
}

View File

@ -2853,7 +2853,8 @@ class ArrayList : public FixedArray {
inline void SetLength(int length);
inline Object* Get(int index);
inline Object** Slot(int index);
inline void Set(int index, Object* obj);
inline void Set(int index, Object* obj,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
inline void Clear(int index, Object* undefined);
bool IsFull();
DECLARE_CAST(ArrayList)

View File

@ -410,6 +410,7 @@ void RelocInfo::set_target_object(Object* target,
target->IsHeapObject()) {
host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
host(), this, HeapObject::cast(target));
host()->GetHeap()->RecordWriteIntoCode(host(), this, target);
}
}

View File

@ -2966,15 +2966,8 @@ void MacroAssembler::Push(Handle<Object> source) {
void MacroAssembler::MoveHeapObject(Register result,
Handle<Object> object) {
AllowDeferredHandleDereference using_raw_address;
DCHECK(object->IsHeapObject());
if (isolate()->heap()->InNewSpace(*object)) {
Handle<Cell> cell = isolate()->factory()->NewCell(object);
Move(result, cell, RelocInfo::CELL);
movp(result, Operand(result, 0));
} else {
Move(result, object, RelocInfo::EMBEDDED_OBJECT);
}
Move(result, object, RelocInfo::EMBEDDED_OBJECT);
}

View File

@ -927,7 +927,6 @@ class MacroAssembler: public Assembler {
AllowDeferredHandleDereference using_raw_address;
DCHECK(!RelocInfo::IsNone(rmode));
DCHECK(value->IsHeapObject());
DCHECK(!isolate()->heap()->InNewSpace(*value));
movp(dst, reinterpret_cast<void*>(value.location()), rmode);
}

View File

@ -140,6 +140,7 @@ void RelocInfo::set_target_object(Object* target,
target->IsHeapObject()) {
host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
host(), this, HeapObject::cast(target));
host()->GetHeap()->RecordWriteIntoCode(host(), this, target);
}
}

View File

@ -4817,6 +4817,67 @@ TEST(ObjectsInOptimizedCodeAreWeak) {
CHECK(code->marked_for_deoptimization());
}
TEST(NewSpaceObjectsInOptimizedCode) {
if (i::FLAG_always_opt || !i::FLAG_crankshaft || i::FLAG_turbo) return;
i::FLAG_weak_embedded_objects_in_optimized_code = true;
i::FLAG_allow_natives_syntax = true;
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
v8::internal::Heap* heap = CcTest::heap();
if (!isolate->use_crankshaft()) return;
HandleScope outer_scope(heap->isolate());
Handle<Code> code;
{
LocalContext context;
HandleScope scope(heap->isolate());
CompileRun(
"var foo;"
"var bar;"
"(function() {"
" function foo_func(x) { with (x) { return 1 + x; } };"
" %NeverOptimizeFunction(foo_func);"
" function bar_func() {"
" return foo(1);"
" };"
" bar = bar_func;"
" foo = foo_func;"
" bar_func();"
" bar_func();"
" bar_func();"
" %OptimizeFunctionOnNextCall(bar_func);"
" bar_func();"
"})();");
Handle<JSFunction> bar = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
*v8::Local<v8::Function>::Cast(CcTest::global()
->Get(context.local(), v8_str("bar"))
.ToLocalChecked())));
Handle<JSFunction> foo = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
*v8::Local<v8::Function>::Cast(CcTest::global()
->Get(context.local(), v8_str("foo"))
.ToLocalChecked())));
CHECK(heap->InNewSpace(*foo));
heap->CollectGarbage(NEW_SPACE);
heap->CollectGarbage(NEW_SPACE);
CHECK(!heap->InNewSpace(*foo));
#ifdef VERIFY_HEAP
heap->Verify();
#endif
CHECK(!bar->code()->marked_for_deoptimization());
code = scope.CloseAndEscape(Handle<Code>(bar->code()));
}
// Now make sure that a gc should get rid of the function
for (int i = 0; i < 4; i++) {
heap->CollectAllGarbage();
}
CHECK(code->marked_for_deoptimization());
}
TEST(NoWeakHashTableLeakWithIncrementalMarking) {
if (i::FLAG_always_opt || !i::FLAG_crankshaft) return;

View File

@ -1852,15 +1852,19 @@ TEST(CodeSerializerCell) {
assembler.enable_serializer();
Handle<HeapNumber> number = isolate->factory()->NewHeapNumber(0.3);
CHECK(isolate->heap()->InNewSpace(*number));
MacroAssembler* masm = &assembler;
masm->MoveHeapObject(rax, number);
masm->ret(0);
CodeDesc desc;
masm->GetCode(&desc);
Handle<Code> code = isolate->factory()->NewCode(
desc, Code::ComputeFlags(Code::FUNCTION), masm->CodeObject());
code->set_has_reloc_info_for_serialization(true);
Handle<Code> code;
{
MacroAssembler* masm = &assembler;
Handle<Cell> cell = isolate->factory()->NewCell(number);
masm->Move(rax, cell, RelocInfo::CELL);
masm->movp(rax, Operand(rax, 0));
masm->ret(0);
CodeDesc desc;
masm->GetCode(&desc);
code = isolate->factory()->NewCode(desc, Code::ComputeFlags(Code::FUNCTION),
masm->CodeObject());
code->set_has_reloc_info_for_serialization(true);
}
RelocIterator rit1(*code, 1 << RelocInfo::CELL);
CHECK_EQ(*number, rit1.rinfo()->target_cell()->value());