Commit 28f9412c authored by vegorov@chromium.org's avatar vegorov@chromium.org

Generalize virtually dispatched scavenger to virtually dispatched specialized visitors.

Review URL: http://codereview.chromium.org/3066044

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5246 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent fb039823
......@@ -84,6 +84,7 @@ SOURCES = {
mark-compact.cc
messages.cc
objects.cc
objects-visiting.cc
oprofile-agent.cc
parser.cc
profile-generator.cc
......
......@@ -190,6 +190,29 @@ void RelocInfo::Visit(ObjectVisitor* visitor) {
}
template<typename StaticVisitor>
void RelocInfo::Visit() {
RelocInfo::Mode mode = rmode();
if (mode == RelocInfo::EMBEDDED_OBJECT) {
StaticVisitor::VisitPointer(target_object_address());
} else if (RelocInfo::IsCodeTarget(mode)) {
StaticVisitor::VisitCodeTarget(this);
} else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
StaticVisitor::VisitExternalReference(target_reference_address());
#ifdef ENABLE_DEBUGGER_SUPPORT
} else if (Debug::has_break_points() &&
((RelocInfo::IsJSReturn(mode) &&
IsPatchedReturnSequence()) ||
(RelocInfo::IsDebugBreakSlot(mode) &&
IsPatchedDebugBreakSlotSequence()))) {
StaticVisitor::VisitDebugTarget(this);
#endif
} else if (mode == RelocInfo::RUNTIME_ENTRY) {
StaticVisitor::VisitRuntimeEntry(this);
}
}
Operand::Operand(int32_t immediate, RelocInfo::Mode rmode) {
rm_ = no_reg;
imm32_ = immediate;
......
......@@ -235,6 +235,7 @@ class RelocInfo BASE_EMBEDDED {
INLINE(void set_call_object(Object* target));
INLINE(Object** call_object_address());
template<typename StaticVisitor> inline void Visit();
inline void Visit(ObjectVisitor* v);
// Patch the code with some other code.
......
......@@ -36,6 +36,7 @@
#include "global-handles.h"
#include "macro-assembler.h"
#include "natives.h"
#include "objects-visiting.h"
#include "snapshot.h"
#include "stub-cache.h"
......@@ -813,9 +814,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
initial_map->set_instance_size(
initial_map->instance_size() + 5 * kPointerSize);
initial_map->set_instance_descriptors(*descriptors);
initial_map->set_scavenger(
Heap::GetScavenger(initial_map->instance_type(),
initial_map->instance_size()));
initial_map->set_visitor_id(StaticVisitorBase::GetVisitorId(*initial_map));
}
{ // -- J S O N
......
......@@ -32,6 +32,7 @@
#include "execution.h"
#include "factory.h"
#include "macro-assembler.h"
#include "objects-visiting.h"
namespace v8 {
namespace internal {
......@@ -277,8 +278,7 @@ Handle<Map> Factory::CopyMap(Handle<Map> src,
copy->set_inobject_properties(inobject_properties);
copy->set_unused_property_fields(inobject_properties);
copy->set_instance_size(copy->instance_size() + instance_size_delta);
copy->set_scavenger(Heap::GetScavenger(copy->instance_type(),
copy->instance_size()));
copy->set_visitor_id(StaticVisitorBase::GetVisitorId(*copy));
return copy;
}
......
This diff is collapsed.
......@@ -983,8 +983,6 @@ class Heap : public AllStatic {
static void RecordStats(HeapStats* stats, bool take_snapshot = false);
static Scavenger GetScavenger(int instance_type, int instance_size);
// Copy block of memory from src to dst. Size of block should be aligned
// by pointer size.
static inline void CopyBlock(Address dst, Address src, int byte_size);
......@@ -1725,6 +1723,7 @@ class GCTracer BASE_EMBEDDED {
EXTERNAL,
MC_MARK,
MC_SWEEP,
MC_SWEEP_NEWSPACE,
MC_COMPACT,
MC_FLUSH_CODE,
kNumberOfScopes
......
......@@ -183,6 +183,30 @@ void RelocInfo::Visit(ObjectVisitor* visitor) {
}
template<typename StaticVisitor>
void RelocInfo::Visit() {
RelocInfo::Mode mode = rmode();
if (mode == RelocInfo::EMBEDDED_OBJECT) {
StaticVisitor::VisitPointer(target_object_address());
} else if (RelocInfo::IsCodeTarget(mode)) {
StaticVisitor::VisitCodeTarget(this);
} else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
StaticVisitor::VisitExternalReference(target_reference_address());
#ifdef ENABLE_DEBUGGER_SUPPORT
} else if (Debug::has_break_points() &&
((RelocInfo::IsJSReturn(mode) &&
IsPatchedReturnSequence()) ||
(RelocInfo::IsDebugBreakSlot(mode) &&
IsPatchedDebugBreakSlotSequence()))) {
StaticVisitor::VisitDebugTarget(this);
#endif
} else if (mode == RelocInfo::RUNTIME_ENTRY) {
StaticVisitor::VisitRuntimeEntry(this);
}
}
Immediate::Immediate(int x) {
x_ = x;
rmode_ = RelocInfo::NONE;
......
This diff is collapsed.
......@@ -86,6 +86,9 @@ class MarkCompactCollector: public AllStatic {
force_compaction_ = value;
}
static void Initialize();
// Prepares for GC by resetting relocation info in old and map spaces and
// choosing spaces to compact.
static void Prepare(GCTracer* tracer);
......@@ -171,6 +174,7 @@ class MarkCompactCollector: public AllStatic {
friend class RootMarkingVisitor;
friend class MarkingVisitor;
friend class StaticMarkingVisitor;
// Marking operations for objects reachable from roots.
static void MarkLiveObjects();
......@@ -214,17 +218,17 @@ class MarkCompactCollector: public AllStatic {
// Mark all objects in an object group with at least one marked
// object, then all objects reachable from marked objects in object
// groups, and repeat.
static void ProcessObjectGroups(MarkingVisitor* visitor);
static void ProcessObjectGroups();
// Mark objects reachable (transitively) from objects in the marking stack
// or overflowed in the heap.
static void ProcessMarkingStack(MarkingVisitor* visitor);
static void ProcessMarkingStack();
// Mark objects reachable (transitively) from objects in the marking
// stack. This function empties the marking stack, but may leave
// overflowed objects in the heap, in which case the marking stack's
// overflow flag will be set.
static void EmptyMarkingStack(MarkingVisitor* visitor);
static void EmptyMarkingStack();
// Refill the marking stack with overflowed objects from the heap. This
// function either leaves the marking stack full or clears the overflow
......
......@@ -2060,21 +2060,8 @@ void ExternalFloatArray::set(int index, float value) {
ptr[index] = value;
}
inline Scavenger Map::scavenger() {
Scavenger callback = reinterpret_cast<Scavenger>(
READ_INTPTR_FIELD(this, kScavengerCallbackOffset));
ASSERT(callback == Heap::GetScavenger(instance_type(),
instance_size()));
return callback;
}
inline void Map::set_scavenger(Scavenger callback) {
WRITE_INTPTR_FIELD(this,
kScavengerCallbackOffset,
reinterpret_cast<intptr_t>(callback));
}
INT_ACCESSORS(Map, visitor_id, kScavengerCallbackOffset)
int Map::instance_size() {
return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
......@@ -2099,7 +2086,7 @@ int HeapObject::SizeFromMap(Map* map) {
(kStringTag | kConsStringTag) ||
instance_type == JS_ARRAY_TYPE) return map->instance_size();
if (instance_type == FIXED_ARRAY_TYPE) {
return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
return FixedArray::BodyDescriptor::SizeOf(map, this);
}
if (instance_type == BYTE_ARRAY_TYPE) {
return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
......@@ -2819,12 +2806,6 @@ void Proxy::set_proxy(Address value) {
}
void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
visitor->VisitExternalReference(
reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
}
ACCESSORS(JSValue, value, Object, kValueOffset)
......@@ -3308,6 +3289,74 @@ Object* FixedArray::Copy() {
}
int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
return map->instance_size();
}
void Proxy::ProxyIterateBody(ObjectVisitor* v) {
v->VisitExternalReference(
reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
}
template<typename StaticVisitor>
void Proxy::ProxyIterateBody() {
StaticVisitor::VisitExternalReference(
reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
}
void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
typedef v8::String::ExternalAsciiStringResource Resource;
v->VisitExternalAsciiString(
reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
}
template<typename StaticVisitor>
void ExternalAsciiString::ExternalAsciiStringIterateBody() {
typedef v8::String::ExternalAsciiStringResource Resource;
StaticVisitor::VisitExternalAsciiString(
reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
}
void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
typedef v8::String::ExternalStringResource Resource;
v->VisitExternalTwoByteString(
reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
}
template<typename StaticVisitor>
void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
typedef v8::String::ExternalStringResource Resource;
StaticVisitor::VisitExternalTwoByteString(
reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
}
#define SLOT_ADDR(obj, offset) \
reinterpret_cast<Object**>((obj)->address() + offset)
template<int start_offset, int end_offset, int size>
void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
HeapObject* obj,
ObjectVisitor* v) {
v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, end_offset));
}
template<int start_offset>
void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
int object_size,
ObjectVisitor* v) {
v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, object_size));
}
#undef SLOT_ADDR
#undef CAST_ACCESSOR
#undef INT_ACCESSORS
#undef SMI_ACCESSORS
......
// Copyright 2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "v8.h"
#include "ic-inl.h"
#include "objects-visiting.h"
namespace v8 {
namespace internal {
static inline bool IsShortcutCandidate(int type) {
return ((type & kShortcutTypeMask) == kShortcutTypeTag);
}
StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId(
int instance_type,
int instance_size) {
if (instance_type < FIRST_NONSTRING_TYPE) {
switch (instance_type & kStringRepresentationMask) {
case kSeqStringTag:
if ((instance_type & kStringEncodingMask) == kAsciiStringTag) {
return kVisitSeqAsciiString;
} else {
return kVisitSeqTwoByteString;
}
case kConsStringTag:
if (IsShortcutCandidate(instance_type)) {
return kVisitShortcutCandidate;
} else {
return kVisitConsString;
}
case kExternalStringTag:
return GetVisitorIdForSize(kVisitDataObject,
kVisitDataObjectGeneric,
ExternalString::kSize);
}
UNREACHABLE();
}
switch (instance_type) {
case BYTE_ARRAY_TYPE:
return kVisitByteArray;
case FIXED_ARRAY_TYPE:
return kVisitFixedArray;
case ODDBALL_TYPE:
return kVisitOddball;
case MAP_TYPE:
return kVisitMap;
case CODE_TYPE:
return kVisitCode;
case JS_GLOBAL_PROPERTY_CELL_TYPE:
return kVisitPropertyCell;
case SHARED_FUNCTION_INFO_TYPE:
return kVisitSharedFunctionInfo;
case PROXY_TYPE:
return GetVisitorIdForSize(kVisitDataObject,
kVisitDataObjectGeneric,
Proxy::kSize);
case FILLER_TYPE:
return kVisitDataObjectGeneric;
case JS_OBJECT_TYPE:
case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
case JS_VALUE_TYPE:
case JS_ARRAY_TYPE:
case JS_REGEXP_TYPE:
case JS_FUNCTION_TYPE:
case JS_GLOBAL_PROXY_TYPE:
case JS_GLOBAL_OBJECT_TYPE:
case JS_BUILTINS_OBJECT_TYPE:
return GetVisitorIdForSize(kVisitJSObject,
kVisitJSObjectGeneric,
instance_size);
case HEAP_NUMBER_TYPE:
case PIXEL_ARRAY_TYPE:
case EXTERNAL_BYTE_ARRAY_TYPE:
case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
case EXTERNAL_SHORT_ARRAY_TYPE:
case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
case EXTERNAL_INT_ARRAY_TYPE:
case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
case EXTERNAL_FLOAT_ARRAY_TYPE:
return GetVisitorIdForSize(kVisitDataObject,
kVisitDataObjectGeneric,
instance_size);
#define MAKE_STRUCT_CASE(NAME, Name, name) \
case NAME##_TYPE:
STRUCT_LIST(MAKE_STRUCT_CASE)
#undef MAKE_STRUCT_CASE
return GetVisitorIdForSize(kVisitStruct,
kVisitStructGeneric,
instance_size);
default:
UNREACHABLE();
return kVisitorIdCount;
}
}
} } // namespace v8::internal
This diff is collapsed.
......@@ -33,6 +33,7 @@
#include "debug.h"
#include "execution.h"
#include "objects-inl.h"
#include "objects-visiting.h"
#include "macro-assembler.h"
#include "scanner.h"
#include "scopeinfo.h"
......@@ -1042,7 +1043,7 @@ int HeapObject::SlowSizeFromMap(Map* map) {
switch (instance_type) {
case FIXED_ARRAY_TYPE:
return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
return FixedArray::BodyDescriptor::SizeOf(map, this);
case BYTE_ARRAY_TYPE:
return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
case CODE_TYPE:
......@@ -1073,7 +1074,7 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
case kSeqStringTag:
break;
case kConsStringTag:
reinterpret_cast<ConsString*>(this)->ConsStringIterateBody(v);
ConsString::BodyDescriptor::IterateBody(this, v);
break;
case kExternalStringTag:
if ((type & kStringEncodingMask) == kAsciiStringTag) {
......@@ -1090,7 +1091,7 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
switch (type) {
case FIXED_ARRAY_TYPE:
reinterpret_cast<FixedArray*>(this)->FixedArrayIterateBody(v);
FixedArray::BodyDescriptor::IterateBody(this, object_size, v);
break;
case JS_OBJECT_TYPE:
case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
......@@ -1101,23 +1102,22 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
case JS_GLOBAL_PROXY_TYPE:
case JS_GLOBAL_OBJECT_TYPE:
case JS_BUILTINS_OBJECT_TYPE:
reinterpret_cast<JSObject*>(this)->JSObjectIterateBody(object_size, v);
JSObject::BodyDescriptor::IterateBody(this, object_size, v);
break;
case ODDBALL_TYPE:
reinterpret_cast<Oddball*>(this)->OddballIterateBody(v);
Oddball::BodyDescriptor::IterateBody(this, v);
break;
case PROXY_TYPE:
reinterpret_cast<Proxy*>(this)->ProxyIterateBody(v);
break;
case MAP_TYPE:
reinterpret_cast<Map*>(this)->MapIterateBody(v);
Map::BodyDescriptor::IterateBody(this, v);
break;
case CODE_TYPE:
reinterpret_cast<Code*>(this)->CodeIterateBody(v);
break;
case JS_GLOBAL_PROPERTY_CELL_TYPE:
reinterpret_cast<JSGlobalPropertyCell*>(this)
->JSGlobalPropertyCellIterateBody(v);
JSGlobalPropertyCell::BodyDescriptor::IterateBody(this, v);
break;
case HEAP_NUMBER_TYPE:
case FILLER_TYPE:
......@@ -1131,16 +1131,15 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
case EXTERNAL_FLOAT_ARRAY_TYPE:
break;
case SHARED_FUNCTION_INFO_TYPE: {
SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(this);
shared->SharedFunctionInfoIterateBody(v);
case SHARED_FUNCTION_INFO_TYPE:
SharedFunctionInfo::BodyDescriptor::IterateBody(this, v);
break;
}
#define MAKE_STRUCT_CASE(NAME, Name, name) \
case NAME##_TYPE:
STRUCT_LIST(MAKE_STRUCT_CASE)
#undef MAKE_STRUCT_CASE
IterateStructBody(object_size, v);
StructBodyDescriptor::IterateBody(this, object_size, v);
break;
default:
PrintF("Unknown type: %d\n", type);
......@@ -1209,12 +1208,6 @@ String* JSObject::constructor_name() {
}
void JSObject::JSObjectIterateBody(int object_size, ObjectVisitor* v) {
// Iterate over all fields in the body. Assumes all are Object*.
IteratePointers(v, kPropertiesOffset, object_size);
}
Object* JSObject::AddFastPropertyUsingMap(Map* new_map,
String* name,
Object* value) {
......@@ -2190,8 +2183,7 @@ Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode,
int new_instance_size = map()->instance_size() - instance_size_delta;
new_map->set_inobject_properties(0);
new_map->set_instance_size(new_instance_size);
new_map->set_scavenger(Heap::GetScavenger(new_map->instance_type(),
new_map->instance_size()));
new_map->set_visitor_id(StaticVisitorBase::GetVisitorId(new_map));
Heap::CreateFillerObjectAt(this->address() + new_instance_size,
instance_size_delta);
}
......@@ -3407,11 +3399,6 @@ void CodeCacheHashTable::RemoveByIndex(int index) {
}
void FixedArray::FixedArrayIterateBody(ObjectVisitor* v) {
IteratePointers(v, kHeaderSize, kHeaderSize + length() * kPointerSize);
}
static bool HasKey(FixedArray* array, Object* key) {
int len0 = array->length();
for (int i = 0; i < len0; i++) {
......@@ -4501,16 +4488,6 @@ void ConsString::ConsStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
}
void ConsString::ConsStringIterateBody(ObjectVisitor* v) {
IteratePointers(v, kFirstOffset, kSecondOffset + kPointerSize);
}
void JSGlobalPropertyCell::JSGlobalPropertyCellIterateBody(ObjectVisitor* v) {
IteratePointers(v, kValueOffset, kValueOffset + kPointerSize);
}
uint16_t ConsString::ConsStringGet(int index) {
ASSERT(index >= 0 && index < this->length());
......@@ -4614,24 +4591,6 @@ void String::WriteToFlat(String* src,
}
#define FIELD_ADDR(p, offset) \
(reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
typedef v8::String::ExternalAsciiStringResource Resource;
v->VisitExternalAsciiString(
reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
}
void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
typedef v8::String::ExternalStringResource Resource;
v->VisitExternalTwoByteString(
reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
}
#undef FIELD_ADDR
template <typename IteratorA, typename IteratorB>
static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) {
// General slow case check. We know that the ia and ib iterators
......@@ -5035,12 +4994,6 @@ void Map::ClearNonLiveTransitions(Object* real_prototype) {
}
void Map::MapIterateBody(ObjectVisitor* v) {
// Assumes all Object* members are contiguously allocated!
IteratePointers(v, kPointerFieldsBeginOffset, kPointerFieldsEndOffset);
}
Object* JSFunction::SetInstancePrototype(Object* value) {
ASSERT(value->IsJSObject());
......@@ -5104,12 +5057,6 @@ Context* JSFunction::GlobalContextFromLiterals(FixedArray* literals) {
}
void Oddball::OddballIterateBody(ObjectVisitor* v) {
// Assumes all Object* members are contiguously allocated!
IteratePointers(v, kToStringOffset, kToNumberOffset + kPointerSize);
}
Object* Oddball::Initialize(const char* to_string, Object* to_number) {
Object* symbol = Heap::LookupAsciiSymbol(to_string);
if (symbol->IsFailure()) return symbol;
......@@ -5282,13 +5229,6 @@ void SharedFunctionInfo::SourceCodePrint(StringStream* accumulator,
}
void SharedFunctionInfo::SharedFunctionInfoIterateBody(ObjectVisitor* v) {
IteratePointers(v,
kNameOffset,
kThisPropertyAssignmentsOffset + kPointerSize);
}
void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
......@@ -5310,28 +5250,6 @@ void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
}
void Code::CodeIterateBody(ObjectVisitor* v) {
int mode_mask = RelocInfo::kCodeTargetMask |
RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
RelocInfo::ModeMask(RelocInfo::JS_RETURN) |
RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
// Use the relocation info pointer before it is visited by
// the heap compaction in the next statement.
RelocIterator it(this, mode_mask);
IteratePointers(v,
kRelocationInfoOffset,
kRelocationInfoOffset + kPointerSize);
for (; !it.done(); it.next()) {
it.rinfo()->Visit(v);
}
}
void Code::Relocate(intptr_t delta) {
for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
it.rinfo()->apply(delta);
......
......@@ -1106,6 +1106,51 @@ class HeapObject: public Object {
};
#define SLOT_ADDR(obj, offset) \
reinterpret_cast<Object**>((obj)->address() + offset)
// This class describes a body of an object of a fixed size
// in which all pointer fields are located in the [start_offset, end_offset)
// interval.
template<int start_offset, int end_offset, int size>
class FixedBodyDescriptor {
public:
static const int kStartOffset = start_offset;
static const int kEndOffset = end_offset;
static const int kSize = size;
static inline void IterateBody(HeapObject* obj, ObjectVisitor* v);
template<typename StaticVisitor>
static inline void IterateBody(HeapObject* obj) {
StaticVisitor::VisitPointers(SLOT_ADDR(obj, start_offset),
SLOT_ADDR(obj, end_offset));
}
};
// This class describes a body of an object of a variable size
// in which all pointer fields are located in the [start_offset, object_size)
// interval.
template<int start_offset>
class FlexibleBodyDescriptor {
public:
static const int kStartOffset = start_offset;
static inline void IterateBody(HeapObject* obj,
int object_size,
ObjectVisitor* v);
template<typename StaticVisitor>
static inline void IterateBody(HeapObject* obj, int object_size) {
StaticVisitor::VisitPointers(SLOT_ADDR(obj, start_offset),
SLOT_ADDR(obj, object_size));
}
};
#undef SLOT_ADDR
// The HeapNumber class describes heap allocated numbers that cannot be
// represented in a Smi (small integer)
class HeapNumber: public HeapObject {
......@@ -1522,7 +1567,6 @@ class JSObject: public HeapObject {
// Dispatched behavior.
void JSObjectIterateBody(int object_size, ObjectVisitor* v);
void JSObjectShortPrint(StringStream* accumulator);
#ifdef DEBUG
void JSObjectPrint();
......@@ -1578,6 +1622,11 @@ class JSObject: public HeapObject {
STATIC_CHECK(kHeaderSize == Internals::kJSObjectHeaderSize);
class BodyDescriptor : public FlexibleBodyDescriptor<kPropertiesOffset> {
public:
static inline int SizeOf(Map* map, HeapObject* object);
};
private:
Object* GetElementWithCallback(Object* receiver,
Object* structure,
......@@ -1692,8 +1741,6 @@ class FixedArray: public HeapObject {
static const int kMaxLength = (kMaxSize - kHeaderSize) / kPointerSize;
// Dispatched behavior.
int FixedArraySize() { return SizeFor(length()); }
void FixedArrayIterateBody(ObjectVisitor* v);
#ifdef DEBUG
void FixedArrayPrint();
void FixedArrayVerify();
......@@ -1711,6 +1758,13 @@ class FixedArray: public HeapObject {
// object, the prefix of this array is sorted.
void SortPairs(FixedArray* numbers, uint32_t len);
class BodyDescriptor : public FlexibleBodyDescriptor<kHeaderSize> {
public:
static inline int SizeOf(Map* map, HeapObject* object) {
return SizeFor(reinterpret_cast<FixedArray*>(object)->length());
}
};
protected:
// Set operation on FixedArray without using write barriers. Can
// only be used for storing old space objects or smis.
......@@ -2426,7 +2480,9 @@ class ByteArray: public HeapObject {
static inline ByteArray* cast(Object* obj);
// Dispatched behavior.
int ByteArraySize() { return SizeFor(length()); }
inline int ByteArraySize() {
return SizeFor(this->length());
}
#ifdef DEBUG
void ByteArrayPrint();
void ByteArrayVerify();
......@@ -2847,7 +2903,10 @@ class Code: public HeapObject {
// Dispatched behavior.
int CodeSize() { return SizeFor(body_size()); }
void CodeIterateBody(ObjectVisitor* v);
inline void CodeIterateBody(ObjectVisitor* v);
template<typename StaticVisitor>
inline void CodeIterateBody();
#ifdef DEBUG
void CodePrint();
void CodeVerify();
......@@ -2893,7 +2952,6 @@ class Code: public HeapObject {
DISALLOW_IMPLICIT_CONSTRUCTORS(Code);
};
typedef void (*Scavenger)(Map* map, HeapObject** slot, HeapObject* object);
// All heap objects have a Map that describes their structure.
// A Map contains information about:
......@@ -3089,18 +3147,13 @@ class Map: public HeapObject {
void ClearNonLiveTransitions(Object* real_prototype);
// Dispatched behavior.
void MapIterateBody(ObjectVisitor* v);
#ifdef DEBUG
void MapPrint();
void MapVerify();
#endif
inline Scavenger scavenger();
inline void set_scavenger(Scavenger callback);
inline void Scavenge(HeapObject** slot, HeapObject* obj) {
scavenger()(this, slot, obj);
}
inline int visitor_id();
inline void set_visitor_id(int visitor_id);
static const int kMaxPreAllocatedPropertyFields = 255;
......@@ -3160,6 +3213,10 @@ class Map: public HeapObject {
static const int kCodeCacheEntryNameOffset = 0;
static const int kCodeCacheEntryCodeOffset = 1;
typedef FixedBodyDescriptor<kPointerFieldsBeginOffset,
kPointerFieldsEndOffset,
kSize> BodyDescriptor;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Map);
};
......@@ -3414,7 +3471,6 @@ class SharedFunctionInfo: public HeapObject {
int CalculateInObjectProperties();
// Dispatched behavior.
void SharedFunctionInfoIterateBody(ObjectVisitor* v);
// Set max_length to -1 for unlimited length.
void SourceCodePrint(StringStream* accumulator, int max_length);
#ifdef DEBUG
......@@ -3503,6 +3559,10 @@ class SharedFunctionInfo: public HeapObject {
#endif
static const int kAlignedSize = POINTER_SIZE_ALIGN(kSize);
typedef FixedBodyDescriptor<kNameOffset,
kThisPropertyAssignmentsOffset + kPointerSize,
kSize> BodyDescriptor;
private:
// Bit positions in start_position_and_type.
// The source code start position is in the 30 most significant bits of
......@@ -4553,11 +4613,6 @@ class ConsString: public String {
// Casting.
static inline ConsString* cast(Object* obj);
// Garbage collection support. This method is called during garbage
// collection to iterate through the heap pointers in the body of
// the ConsString.
void ConsStringIterateBody(ObjectVisitor* v);
// Layout description.
static const int kFirstOffset = POINTER_SIZE_ALIGN(String::kSize);
static const int kSecondOffset = kFirstOffset + kPointerSize;
......@@ -4574,6 +4629,9 @@ class ConsString: public String {
// Minimum length for a cons string.
static const int kMinLength = 13;
typedef FixedBodyDescriptor<kFirstOffset, kSecondOffset + kPointerSize, kSize>
BodyDescriptor;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ConsString);
};
......@@ -4623,7 +4681,10 @@ class ExternalAsciiString: public ExternalString {
static inline ExternalAsciiString* cast(Object* obj);
// Garbage collection support.
void ExternalAsciiStringIterateBody(ObjectVisitor* v);
inline void ExternalAsciiStringIterateBody(ObjectVisitor* v);
template<typename StaticVisitor>
inline void ExternalAsciiStringIterateBody();
// Support for StringInputBuffer.
const unibrow::byte* ExternalAsciiStringReadBlock(unsigned* remaining,
......@@ -4660,7 +4721,11 @@ class ExternalTwoByteString: public ExternalString {
static inline ExternalTwoByteString* cast(Object* obj);
// Garbage collection support.
void ExternalTwoByteStringIterateBody(ObjectVisitor* v);
inline void ExternalTwoByteStringIterateBody(ObjectVisitor* v);
template<typename StaticVisitor>
inline void ExternalTwoByteStringIterateBody();
// Support for StringInputBuffer.
void ExternalTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
......@@ -4771,7 +4836,6 @@ class Oddball: public HeapObject {
static inline Oddball* cast(Object* obj);
// Dispatched behavior.
void OddballIterateBody(ObjectVisitor* v);
#ifdef DEBUG
void OddballVerify();
#endif
......@@ -4784,6 +4848,10 @@ class Oddball: public HeapObject {
static const int kToNumberOffset = kToStringOffset + kPointerSize;
static const int kSize = kToNumberOffset + kPointerSize;
typedef FixedBodyDescriptor<kToStringOffset,
kToNumberOffset + kPointerSize,
kSize> BodyDescriptor;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Oddball);
};
......@@ -4797,8 +4865,6 @@ class JSGlobalPropertyCell: public HeapObject {
// Casting.
static inline JSGlobalPropertyCell* cast(Object* obj);
// Dispatched behavior.
void JSGlobalPropertyCellIterateBody(ObjectVisitor* v);
#ifdef DEBUG
void JSGlobalPropertyCellVerify();
void JSGlobalPropertyCellPrint();
......@@ -4808,6 +4874,10 @@ class JSGlobalPropertyCell: public HeapObject {
static const int kValueOffset = HeapObject::kHeaderSize;
static const int kSize = kValueOffset + kPointerSize;
typedef FixedBodyDescriptor<kValueOffset,
kValueOffset + kPointerSize,
kSize> BodyDescriptor;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalPropertyCell);
};
......@@ -4828,6 +4898,10 @@ class Proxy: public HeapObject {
// Dispatched behavior.
inline void ProxyIterateBody(ObjectVisitor* v);
template<typename StaticVisitor>
inline void ProxyIterateBody();
#ifdef DEBUG
void ProxyPrint();
void ProxyVerify();
......@@ -5345,6 +5419,15 @@ class ObjectVisitor BASE_EMBEDDED {
};
class StructBodyDescriptor : public
FlexibleBodyDescriptor<HeapObject::kHeaderSize> {
public:
static inline int SizeOf(Map* map, HeapObject* object) {
return map->instance_size();
}
};
// BooleanBit is a helper class for setting and getting a bit in an
// integer or Smi.
class BooleanBit : public AllStatic {
......
......@@ -680,14 +680,6 @@ void Deserializer::ReadObject(int space_number,
LOG(SnapshotPositionEvent(address, source_->position()));
}
ReadChunk(current, limit, space_number, address);
if (space == Heap::map_space()) {
ASSERT(size == Map::kSize);
HeapObject* obj = HeapObject::FromAddress(address);
Map* map = reinterpret_cast<Map*>(obj);
map->set_scavenger(Heap::GetScavenger(map->instance_type(),
map->instance_size()));
}
}
......
......@@ -350,6 +350,29 @@ void RelocInfo::Visit(ObjectVisitor* visitor) {
}
template<typename StaticVisitor>
void RelocInfo::Visit() {
RelocInfo::Mode mode = rmode();
if (mode == RelocInfo::EMBEDDED_OBJECT) {
StaticVisitor::VisitPointer(target_object_address());
} else if (RelocInfo::IsCodeTarget(mode)) {
StaticVisitor::VisitCodeTarget(this);
} else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
StaticVisitor::VisitExternalReference(target_reference_address());
#ifdef ENABLE_DEBUGGER_SUPPORT
} else if (Debug::has_break_points() &&
((RelocInfo::IsJSReturn(mode) &&
IsPatchedReturnSequence()) ||
(RelocInfo::IsDebugBreakSlot(mode) &&
IsPatchedDebugBreakSlotSequence()))) {
StaticVisitor::VisitDebugTarget(this);
#endif
} else if (mode == RelocInfo::RUNTIME_ENTRY) {
StaticVisitor::VisitRuntimeEntry(this);
}
}
// -----------------------------------------------------------------------------
// Implementation of Operand
......
......@@ -38,7 +38,7 @@
from __future__ import with_statement
import sys, types, re, subprocess
import sys, types, re, subprocess, math
def flatten(l):
flat = []
......@@ -262,48 +262,57 @@ plots = [
],
]
def freduce(f, field, trace, init):
return reduce(lambda t,r: f(t, r[field]), trace, init)
def calc_total(trace, field):
return reduce(lambda t,r: t + r[field], trace, 0)
return freduce(lambda t,v: t + v, field, trace, 0)
def calc_max(trace, field):
return reduce(lambda t,r: max(t, r[field]), trace, 0)
return freduce(lambda t,r: max(t, r), field, trace, 0)
def process_trace(filename):
trace = parse_gc_trace(filename)
total_gc = calc_total(trace, 'pause')
max_gc = calc_max(trace, 'pause')
avg_gc = total_gc / len(trace)
def count_nonzero(trace, field):
return freduce(lambda t,r: t if r == 0 else t + 1, field, trace, 0)
total_sweep = calc_total(trace, 'sweep')
max_sweep = calc_max(trace, 'sweep')
total_mark = calc_total(trace, 'mark')
max_mark = calc_max(trace, 'mark')
def process_trace(filename):
trace = parse_gc_trace(filename)
marksweeps = filter(lambda r: r['gc'] == 'ms', trace)
markcompacts = filter(lambda r: r['gc'] == 'mc', trace)
scavenges = filter(lambda r: r['gc'] == 's', trace)
total_scavenge = calc_total(scavenges, 'pause')
max_scavenge = calc_max(scavenges, 'pause')
avg_scavenge = total_scavenge / len(scavenges)
charts = plot_all(plots, trace, filename)
def stats(out, prefix, trace, field):
n = len(trace)
total = calc_total(trace, field)
max = calc_max(trace, field)
avg = total / n
if n > 1:
dev = math.sqrt(freduce(lambda t,r: (r - avg) ** 2, field, trace, 0) /
(n - 1))
else:
dev = 0
out.write('<tr><td>%s</td><td>%d</td><td>%d</td>'
'<td>%d</td><td>%d [dev %f]</td></tr>' %
(prefix, n, total, max, avg, dev))
with open(filename + '.html', 'w') as out:
out.write('<html><body>')
out.write('<table><tr><td>')
out.write('Total in GC: <b>%d</b><br/>' % total_gc)
out.write('Max in GC: <b>%d</b><br/>' % max_gc)
out.write('Avg in GC: <b>%d</b><br/>' % avg_gc)
out.write('</td><td>')
out.write('Total in Scavenge: <b>%d</b><br/>' % total_scavenge)
out.write('Max in Scavenge: <b>%d</b><br/>' % max_scavenge)
out.write('Avg in Scavenge: <b>%d</b><br/>' % avg_scavenge)
out.write('</td><td>')
out.write('Total in Sweep: <b>%d</b><br/>' % total_sweep)
out.write('Max in Sweep: <b>%d</b><br/>' % max_sweep)
out.write('</td><td>')
out.write('Total in Mark: <b>%d</b><br/>' % total_mark)
out.write('Max in Mark: <b>%d</b><br/>' % max_mark)
out.write('</td></tr></table>')
out.write('<table>')
out.write('<tr><td>Phase</td><td>Count</td><td>Time (ms)</td><td>Max</td><td>Avg</td></tr>')
stats(out, 'Total in GC', trace, 'pause')
stats(out, 'Scavenge', scavenges, 'pause')
stats(out, 'MarkSweep', marksweeps, 'pause')
stats(out, 'MarkCompact', markcompacts, 'pause')
stats(out, 'Mark', filter(lambda r: r['mark'] != 0, trace), 'mark')
stats(out, 'Sweep', filter(lambda r: r['sweep'] != 0, trace), 'sweep')
stats(out, 'Flush Code', filter(lambda r: r['flushcode'] != 0, trace), 'flushcode')
stats(out, 'Compact', filter(lambda r: r['compact'] != 0, trace), 'compact')
out.write('</table>')
for chart in charts:
out.write('<img src="%s">' % chart)
out.write('</body></html>')
......
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