Commit 744d61eb authored by ulan@chromium.org's avatar ulan@chromium.org

Fix clearing of dead dependent codes and verify weak embedded maps on full GC.

BUG=172488,172489
R=mstarzinger@chromium.org

Review URL: https://chromiumcodereview.appspot.com/12094036

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13584 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 23ee3f28
......@@ -781,6 +781,18 @@ AlwaysAllocateScope::~AlwaysAllocateScope() {
}
#ifdef VERIFY_HEAP
NoWeakEmbeddedMapsVerificationScope::NoWeakEmbeddedMapsVerificationScope() {
HEAP->no_weak_embedded_maps_verification_scope_depth_++;
}
NoWeakEmbeddedMapsVerificationScope::~NoWeakEmbeddedMapsVerificationScope() {
HEAP->no_weak_embedded_maps_verification_scope_depth_--;
}
#endif
void VerifyPointersVisitor::VisitPointers(Object** start, Object** end) {
for (Object** current = start; current < end; current++) {
if ((*current)->IsHeapObject()) {
......
......@@ -157,6 +157,9 @@ Heap::Heap()
ms_count_at_last_idle_notification_(0),
gc_count_at_last_idle_gc_(0),
scavenges_since_last_idle_round_(kIdleScavengeThreshold),
#ifdef VERIFY_HEAP
no_weak_embedded_maps_verification_scope_depth_(0),
#endif
promotion_queue_(this),
configured_(false),
chunks_queued_for_free_(NULL),
......
......@@ -1322,6 +1322,11 @@ class Heap {
#ifdef VERIFY_HEAP
// Verify the heap is in its normal state before or after a GC.
void Verify();
bool weak_embedded_maps_verification_enabled() {
return no_weak_embedded_maps_verification_scope_depth_ == 0;
}
#endif
#ifdef DEBUG
......@@ -2214,6 +2219,10 @@ class Heap {
unsigned int gc_count_at_last_idle_gc_;
int scavenges_since_last_idle_round_;
#ifdef VERIFY_HEAP
int no_weak_embedded_maps_verification_scope_depth_;
#endif
static const int kMaxMarkSweepsInIdleRound = 7;
static const int kIdleScavengeThreshold = 5;
......@@ -2243,6 +2252,9 @@ class Heap {
friend class MarkCompactCollector;
friend class MarkCompactMarkingVisitor;
friend class MapCompact;
#ifdef VERIFY_HEAP
friend class NoWeakEmbeddedMapsVerificationScope;
#endif
DISALLOW_COPY_AND_ASSIGN(Heap);
};
......@@ -2303,6 +2315,14 @@ class AlwaysAllocateScope {
DisallowAllocationFailure disallow_allocation_failure_;
};
#ifdef VERIFY_HEAP
class NoWeakEmbeddedMapsVerificationScope {
public:
inline NoWeakEmbeddedMapsVerificationScope();
inline ~NoWeakEmbeddedMapsVerificationScope();
};
#endif
// Visitor class to verify interior pointers in spaces that do not contain
// or care about intergenerational references. All heap object pointers have to
......
......@@ -452,6 +452,12 @@ void LChunk::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) {
}
}
}
#ifdef VERIFY_HEAP
// This disables verification of weak embedded maps after full GC.
// AddDependentCode can cause a GC, which would observe the state where
// this code is not yet in the depended code lists of the embedded maps.
NoWeakEmbeddedMapsVerificationScope disable_verification_of_embedded_maps;
#endif
for (int i = 0; i < maps.length(); i++) {
maps.at(i)->AddDependentCode(code);
}
......
......@@ -87,7 +87,7 @@ class VerifyMarkingVisitor: public ObjectVisitor {
void VisitEmbeddedPointer(RelocInfo* rinfo) {
ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
if (!FLAG_weak_embedded_maps_in_optimized_code ||
if (!FLAG_weak_embedded_maps_in_optimized_code || !FLAG_collect_maps ||
rinfo->host()->kind() != Code::OPTIMIZED_FUNCTION ||
!rinfo->target_object()->IsMap() ||
!Map::cast(rinfo->target_object())->CanTransition()) {
......@@ -414,6 +414,13 @@ void MarkCompactCollector::CollectGarbage() {
}
#endif
#ifdef VERIFY_HEAP
if (FLAG_collect_maps && FLAG_weak_embedded_maps_in_optimized_code &&
heap()->weak_embedded_maps_verification_enabled()) {
VerifyWeakEmbeddedMapsInOptimizedCode();
}
#endif
Finish();
if (marking_parity_ == EVEN_MARKING_PARITY) {
......@@ -465,6 +472,19 @@ void MarkCompactCollector::VerifyMarkbitsAreClean() {
CHECK_EQ(0, Page::FromAddress(obj->address())->LiveBytes());
}
}
void MarkCompactCollector::VerifyWeakEmbeddedMapsInOptimizedCode() {
HeapObjectIterator code_iterator(heap()->code_space());
for (HeapObject* obj = code_iterator.Next();
obj != NULL;
obj = code_iterator.Next()) {
Code* code = Code::cast(obj);
if (code->kind() != Code::OPTIMIZED_FUNCTION) continue;
if (code->marked_for_deoptimization()) continue;
code->VerifyEmbeddedMapsDependency();
}
}
#endif // VERIFY_HEAP
......@@ -890,6 +910,7 @@ void MarkCompactCollector::Prepare(GCTracer* tracer) {
#endif
}
class DeoptimizeMarkedCodeFilter : public OptimizedFunctionFilter {
public:
virtual bool TakeFunction(JSFunction* function) {
......@@ -2367,10 +2388,10 @@ void MarkCompactCollector::ClearNonLiveDependentCodes(Map* map) {
if (IsMarked(code) && !code->marked_for_deoptimization()) {
if (new_number_of_codes != i) {
codes->set_code_at(new_number_of_codes, code);
Object** slot = codes->code_slot_at(new_number_of_codes);
RecordSlot(slot, slot, code);
new_number_of_codes++;
}
Object** slot = codes->code_slot_at(new_number_of_codes);
RecordSlot(slot, slot, code);
new_number_of_codes++;
}
}
for (int i = new_number_of_codes; i < number_of_codes; i++) {
......
......@@ -607,6 +607,7 @@ class MarkCompactCollector {
void VerifyMarkbitsAreClean();
static void VerifyMarkbitsAreClean(PagedSpace* space);
static void VerifyMarkbitsAreClean(NewSpace* space);
void VerifyWeakEmbeddedMapsInOptimizedCode();
#endif
// Sweep a single page from the given space conservatively.
......
......@@ -30,6 +30,7 @@
#include "disassembler.h"
#include "disasm.h"
#include "jsregexp.h"
#include "macro-assembler.h"
#include "objects-visiting.h"
namespace v8 {
......@@ -595,6 +596,21 @@ void Code::CodeVerify() {
}
void Code::VerifyEmbeddedMapsDependency() {
int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
RelocInfo::Mode mode = it.rinfo()->rmode();
if (mode == RelocInfo::EMBEDDED_OBJECT &&
it.rinfo()->target_object()->IsMap()) {
Map* map = Map::cast(it.rinfo()->target_object());
if (map->CanTransition()) {
CHECK(map->dependent_codes()->Contains(this));
}
}
}
}
void JSArray::JSArrayVerify() {
JSObjectVerify();
CHECK(length()->IsNumber() || length()->IsUndefined());
......
......@@ -175,8 +175,8 @@ void StaticMarkingVisitor<StaticVisitor>::VisitEmbeddedPointer(
ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
ASSERT(!rinfo->target_object()->IsConsString());
HeapObject* object = HeapObject::cast(rinfo->target_object());
if (!FLAG_weak_embedded_maps_in_optimized_code ||
!FLAG_collect_maps || rinfo->host()->kind() != Code::OPTIMIZED_FUNCTION ||
if (!FLAG_weak_embedded_maps_in_optimized_code || !FLAG_collect_maps ||
rinfo->host()->kind() != Code::OPTIMIZED_FUNCTION ||
!object->IsMap() || !Map::cast(object)->CanTransition()) {
heap->mark_compact_collector()->RecordRelocSlot(rinfo, object);
StaticVisitor::MarkObject(heap, object);
......
......@@ -9501,6 +9501,15 @@ Handle<DependentCodes> DependentCodes::Append(Handle<DependentCodes> codes,
}
bool DependentCodes::Contains(Code* code) {
int limit = number_of_codes();
for (int i = 0; i < limit; i++) {
if (code_at(i) == code) return true;
}
return false;
}
MaybeObject* JSReceiver::SetPrototype(Object* value,
bool skip_hidden_prototypes) {
#ifdef DEBUG
......
......@@ -4547,6 +4547,10 @@ class Code: public HeapObject {
void PrintDeoptLocation(int bailout_id);
#ifdef VERIFY_HEAP
void VerifyEmbeddedMapsDependency();
#endif
// Max loop nesting marker used to postpose OSR. We don't take loop
// nesting that is deeper than 5 levels into account.
static const int kMaxLoopNestingMarker = 6;
......@@ -4693,6 +4697,7 @@ class DependentCodes: public FixedArray {
static Handle<DependentCodes> Append(Handle<DependentCodes> codes,
Handle<Code> value);
static inline DependentCodes* cast(Object* object);
bool Contains(Code* code);
private:
static const int kNumberOfCodesIndex = 0;
static const int kCodesIndex = 1;
......
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