Add FLAG_trace_maps

R=verwaest@chromium.org

Review URL: https://codereview.chromium.org/694533003

Cr-Commit-Position: refs/heads/master@{#25219}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25219 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 3831db00
......@@ -64,6 +64,10 @@ endif
ifeq ($(verifyheap), on)
GYPFLAGS += -Dv8_enable_verify_heap=1
endif
# tracemaps=on
ifeq ($(tracemaps), on)
GYPFLAGS += -Dv8_trace_maps=1
endif
# backtrace=off
ifeq ($(backtrace), off)
GYPFLAGS += -Dv8_enable_backtrace=0
......
......@@ -39,6 +39,8 @@
'v8_enable_verify_heap%': 0,
'v8_trace_maps%': 0,
'v8_use_snapshot%': 'true',
'v8_enable_verify_predictable%': 0,
......@@ -77,6 +79,9 @@
['v8_enable_verify_heap==1', {
'defines': ['VERIFY_HEAP',],
}],
['v8_trace_maps==1', {
'defines': ['TRACE_MAPS',],
}],
['v8_enable_verify_predictable==1', {
'defines': ['VERIFY_PREDICTABLE',],
}],
......
......@@ -852,7 +852,8 @@
'V8_ENABLE_CHECKS',
'OBJECT_PRINT',
'VERIFY_HEAP',
'DEBUG'
'DEBUG',
'TRACE_MAPS'
],
'conditions': [
['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd" or \
......
......@@ -3636,7 +3636,9 @@ static inline bool ObjectSetAccessor(Object* obj,
i::JSObject::SetAccessor(Utils::OpenHandle(obj), info),
false);
if (result->IsUndefined()) return false;
if (fast) i::JSObject::MigrateSlowToFast(Utils::OpenHandle(obj), 0);
if (fast) {
i::JSObject::MigrateSlowToFast(Utils::OpenHandle(obj), 0, "APISetAccessor");
}
return true;
}
......@@ -3822,7 +3824,8 @@ void v8::Object::TurnOnAccessCheck() {
// as optimized code does not always handle access checks.
i::Deoptimizer::DeoptimizeGlobalObject(*obj);
i::Handle<i::Map> new_map = i::Map::Copy(i::Handle<i::Map>(obj->map()));
i::Handle<i::Map> new_map =
i::Map::Copy(i::Handle<i::Map>(obj->map()), "APITurnOnAccessCheck");
new_map->set_is_access_check_needed(true);
i::JSObject::MigrateToMap(obj, new_map);
}
......
......@@ -361,7 +361,7 @@ Handle<Context> Bootstrapper::CreateEnvironment(
static void SetObjectPrototype(Handle<JSObject> object, Handle<Object> proto) {
// object.__proto__ = proto;
Handle<Map> old_map = Handle<Map>(object->map());
Handle<Map> new_map = Map::Copy(old_map);
Handle<Map> new_map = Map::Copy(old_map, "SetObjectPrototype");
new_map->set_prototype(*proto);
JSObject::MigrateToMap(object, new_map);
}
......@@ -510,7 +510,8 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) {
Handle<JSObject> prototype = factory->NewJSObject(
isolate->object_function(),
TENURED);
Handle<Map> map = Map::Copy(handle(prototype->map()));
Handle<Map> map =
Map::Copy(handle(prototype->map()), "EmptyObjectPrototype");
map->set_is_prototype_map(true);
prototype->set_map(*map);
......@@ -1089,7 +1090,7 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> global_object,
initial_map->set_visitor_id(StaticVisitorBase::GetVisitorId(*initial_map));
// RegExp prototype object is itself a RegExp.
Handle<Map> proto_map = Map::Copy(initial_map);
Handle<Map> proto_map = Map::Copy(initial_map, "RegExpPrototype");
proto_map->set_prototype(native_context()->initial_object_prototype());
Handle<JSObject> proto = factory->NewJSObjectFromMap(proto_map);
proto->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex,
......@@ -1244,7 +1245,8 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> global_object,
}
{ // --- aliased arguments map
Handle<Map> map = Map::Copy(isolate->sloppy_arguments_map());
Handle<Map> map =
Map::Copy(isolate->sloppy_arguments_map(), "AliasedArguments");
map->set_elements_kind(SLOPPY_ARGUMENTS_ELEMENTS);
DCHECK_EQ(2, map->pre_allocated_property_fields());
native_context()->set_aliased_arguments_map(*map);
......@@ -1657,7 +1659,7 @@ Handle<JSFunction> Genesis::InstallInternalArray(
array_function->shared()->DontAdaptArguments();
Handle<Map> original_map(array_function->initial_map());
Handle<Map> initial_map = Map::Copy(original_map);
Handle<Map> initial_map = Map::Copy(original_map, "InternalArray");
initial_map->set_elements_kind(elements_kind);
JSFunction::SetInitialMap(array_function, initial_map, prototype);
......@@ -1935,7 +1937,7 @@ bool Genesis::InstallNatives() {
// Create maps for generator functions and their prototypes. Store those
// maps in the native context.
Handle<Map> generator_function_map =
Map::Copy(sloppy_function_map_writable_prototype_);
Map::Copy(sloppy_function_map_writable_prototype_, "GeneratorFunction");
generator_function_map->set_prototype(*generator_function_prototype);
native_context()->set_sloppy_generator_function_map(
*generator_function_map);
......@@ -1966,7 +1968,8 @@ bool Genesis::InstallNatives() {
rw_attribs, poison_pair);
Handle<Map> strict_function_map(native_context()->strict_function_map());
Handle<Map> strict_generator_function_map = Map::Copy(strict_function_map);
Handle<Map> strict_generator_function_map =
Map::Copy(strict_function_map, "StrictGeneratorFunction");
// "arguments" and "caller" already poisoned.
strict_generator_function_map->set_prototype(*generator_function_prototype);
native_context()->set_strict_generator_function_map(
......@@ -2712,6 +2715,15 @@ Genesis::Genesis(Isolate* isolate,
AddToWeakNativeContextList(*native_context());
isolate->set_context(*native_context());
isolate->counters()->contexts_created_by_snapshot()->Increment();
#if TRACE_MAPS
if (FLAG_trace_maps) {
Handle<JSFunction> object_fun = isolate->object_function();
PrintF("[TraceMap: InitialMap map= %p SFI= %d_Object ]\n",
reinterpret_cast<void*>(object_fun->initial_map()),
object_fun->shared()->unique_id());
Map::TraceAllTransitions(object_fun->initial_map());
}
#endif
Handle<GlobalObject> global_object;
Handle<JSGlobalProxy> global_proxy = CreateNewGlobals(
global_proxy_template, maybe_global_proxy, &global_object);
......
......@@ -2077,6 +2077,9 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
share->set_inferred_name(*empty_string(), SKIP_WRITE_BARRIER);
Handle<TypeFeedbackVector> feedback_vector = NewTypeFeedbackVector(0, 0);
share->set_feedback_vector(*feedback_vector, SKIP_WRITE_BARRIER);
#if TRACE_MAPS
share->set_unique_id(isolate()->GetNextUniqueSharedFunctionInfoId());
#endif
share->set_profiler_ticks(0);
share->set_ast_node_count(0);
share->set_counters(0);
......
......@@ -620,6 +620,9 @@ DEFINE_INT(random_seed, 0,
// objects.cc
DEFINE_BOOL(use_verbose_printer, true, "allows verbose printing")
#if TRACE_MAPS
DEFINE_BOOL(trace_maps, false, "trace map creation")
#endif
// parser.cc
DEFINE_BOOL(allow_natives_syntax, false, "allow natives syntax")
......
......@@ -1650,6 +1650,9 @@ Isolate::Isolate(bool enable_serializer)
optimizing_compiler_thread_(NULL),
stress_deopt_count_(0),
next_optimization_id_(0),
#if TRACE_MAPS
next_unique_sfi_id_(0),
#endif
use_counter_callback_(NULL),
basic_block_profiler_(NULL) {
{
......@@ -2356,7 +2359,8 @@ Handle<JSObject> Isolate::GetSymbolRegistry() {
for (unsigned i = 0; i < arraysize(nested); ++i) {
Handle<String> name = factory()->InternalizeUtf8String(nested[i]);
Handle<JSObject> obj = factory()->NewJSObjectFromMap(map);
JSObject::NormalizeProperties(obj, KEEP_INOBJECT_PROPERTIES, 8);
JSObject::NormalizeProperties(obj, KEEP_INOBJECT_PROPERTIES, 8,
"SetupSymbolRegistry");
JSObject::SetProperty(registry, name, obj, STRICT).Assert();
}
}
......
......@@ -1109,6 +1109,10 @@ class Isolate {
std::string GetTurboCfgFileName();
#if TRACE_MAPS
int GetNextUniqueSharedFunctionInfoId() { return next_unique_sfi_id_++; }
#endif
private:
explicit Isolate(bool enable_serializer);
......@@ -1311,6 +1315,10 @@ class Isolate {
int next_optimization_id_;
#if TRACE_MAPS
int next_unique_sfi_id_;
#endif
// List of callbacks when a Call completes.
List<CallCompletedCallback> call_completed_callbacks_;
......
......@@ -5492,6 +5492,9 @@ ACCESSORS(SharedFunctionInfo, optimized_code_map, Object,
ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
ACCESSORS(SharedFunctionInfo, feedback_vector, TypeFeedbackVector,
kFeedbackVectorOffset)
#if TRACE_MAPS
SMI_ACCESSORS(SharedFunctionInfo, unique_id, kUniqueIdOffset)
#endif
ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
kInstanceClassNameOffset)
ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
......
......@@ -1129,4 +1129,38 @@ void TransitionArray::PrintTransitions(std::ostream& os,
#endif // OBJECT_PRINT
#if TRACE_MAPS
void Name::NameShortPrint() {
if (this->IsString()) {
PrintF("%s", String::cast(this)->ToCString().get());
} else {
DCHECK(this->IsSymbol());
Symbol* s = Symbol::cast(this);
if (s->name()->IsUndefined()) {
PrintF("#<%s>", s->PrivateSymbolToName());
} else {
PrintF("<%s>", String::cast(s->name())->ToCString().get());
}
}
}
int Name::NameShortPrint(Vector<char> str) {
if (this->IsString()) {
return SNPrintF(str, "%s", String::cast(this)->ToCString().get());
} else {
DCHECK(this->IsSymbol());
Symbol* s = Symbol::cast(this);
if (s->name()->IsUndefined()) {
return SNPrintF(str, "#<%s>", s->PrivateSymbolToName());
} else {
return SNPrintF(str, "<%s>", String::cast(s->name())->ToCString().get());
}
}
}
#endif // TRACE_MAPS
} } // namespace v8::internal
This diff is collapsed.
......@@ -2049,7 +2049,8 @@ class JSObject: public JSReceiver {
// an initial capacity for holding these properties.
static void NormalizeProperties(Handle<JSObject> object,
PropertyNormalizationMode mode,
int expected_additional_properties);
int expected_additional_properties,
const char* reason);
// Convert and update the elements backing store to be a
// SeededNumberDictionary dictionary. Returns the backing after conversion.
......@@ -2058,7 +2059,7 @@ class JSObject: public JSReceiver {
// Transform slow named properties to fast variants.
static void MigrateSlowToFast(Handle<JSObject> object,
int unused_property_fields);
int unused_property_fields, const char* reason);
// Access fast-case object properties at index.
static Handle<Object> FastPropertyAt(Handle<JSObject> object,
......@@ -5878,7 +5879,8 @@ class Map: public HeapObject {
int descriptor_number,
Handle<Object> value);
static Handle<Map> Normalize(Handle<Map> map, PropertyNormalizationMode mode);
static Handle<Map> Normalize(Handle<Map> map, PropertyNormalizationMode mode,
const char* reason);
// Returns the constructor name (the name (possibly, inferred name) of the
// function that was used to instantiate the object).
......@@ -6087,7 +6089,7 @@ class Map: public HeapObject {
// Returns a copy of the map, with all transitions dropped from the
// instance descriptors.
static Handle<Map> Copy(Handle<Map> map);
static Handle<Map> Copy(Handle<Map> map, const char* reason);
static Handle<Map> Create(Isolate* isolate, int inobject_properties);
// Returns the next free property index (only valid for FAST MODE).
......@@ -6315,6 +6317,11 @@ class Map: public HeapObject {
// The "shared" flags of both this map and |other| are ignored.
bool EquivalentToForNormalization(Map* other, PropertyNormalizationMode mode);
#if TRACE_MAPS
static void TraceTransition(const char* what, Map* from, Map* to, Name* name);
static void TraceAllTransitions(Map* map);
#endif
private:
static void ConnectElementsTransition(Handle<Map> parent, Handle<Map> child);
static void ConnectTransition(Handle<Map> parent, Handle<Map> child,
......@@ -6336,6 +6343,7 @@ class Map: public HeapObject {
Handle<DescriptorArray> descriptors,
TransitionFlag flag,
MaybeHandle<Name> maybe_name,
const char* reason,
SimpleTransitionFlag simple_flag);
static Handle<Map> CopyReplaceDescriptor(Handle<Map> map,
Handle<DescriptorArray> descriptors,
......@@ -6709,6 +6717,13 @@ class SharedFunctionInfo: public HeapObject {
// available.
DECL_ACCESSORS(feedback_vector, TypeFeedbackVector)
#if TRACE_MAPS
// [unique_id] - For --trace-maps purposes, an identifier that's persistent
// even if the GC moves this SharedFunctionInfo.
inline int unique_id() const;
inline void set_unique_id(int value);
#endif
// [instance class name]: class name for instances.
DECL_ACCESSORS(instance_class_name, Object)
......@@ -6955,10 +6970,16 @@ class SharedFunctionInfo: public HeapObject {
static const int kInferredNameOffset = kDebugInfoOffset + kPointerSize;
static const int kFeedbackVectorOffset =
kInferredNameOffset + kPointerSize;
#if TRACE_MAPS
static const int kUniqueIdOffset = kFeedbackVectorOffset + kPointerSize;
static const int kLastPointerFieldOffset = kUniqueIdOffset;
#else
static const int kLastPointerFieldOffset = kFeedbackVectorOffset;
#endif
#if V8_HOST_ARCH_32_BIT
// Smi fields.
static const int kLengthOffset =
kFeedbackVectorOffset + kPointerSize;
static const int kLengthOffset = kLastPointerFieldOffset + kPointerSize;
static const int kFormalParameterCountOffset = kLengthOffset + kPointerSize;
static const int kExpectedNofPropertiesOffset =
kFormalParameterCountOffset + kPointerSize;
......@@ -6994,8 +7015,7 @@ class SharedFunctionInfo: public HeapObject {
// word is not set and thus this word cannot be treated as pointer
// to HeapObject during old space traversal.
#if V8_TARGET_LITTLE_ENDIAN
static const int kLengthOffset =
kFeedbackVectorOffset + kPointerSize;
static const int kLengthOffset = kLastPointerFieldOffset + kPointerSize;
static const int kFormalParameterCountOffset =
kLengthOffset + kIntSize;
......@@ -7029,7 +7049,7 @@ class SharedFunctionInfo: public HeapObject {
#elif V8_TARGET_BIG_ENDIAN
static const int kFormalParameterCountOffset =
kFeedbackVectorOffset + kPointerSize;
kLastPointerFieldOffset + kPointerSize;
static const int kLengthOffset = kFormalParameterCountOffset + kIntSize;
static const int kNumLiteralsOffset = kLengthOffset + kIntSize;
......@@ -7062,7 +7082,7 @@ class SharedFunctionInfo: public HeapObject {
static const int kAlignedSize = POINTER_SIZE_ALIGN(kSize);
typedef FixedBodyDescriptor<kNameOffset,
kFeedbackVectorOffset + kPointerSize,
kLastPointerFieldOffset + kPointerSize,
kSize> BodyDescriptor;
// Bit positions in start_position_and_type.
......@@ -8578,6 +8598,10 @@ class Name: public HeapObject {
DECLARE_CAST(Name)
DECLARE_PRINTER(Name)
#if TRACE_MAPS
void NameShortPrint();
int NameShortPrint(Vector<char> str);
#endif
// Layout description.
static const int kHashFieldSlot = HeapObject::kHeaderSize;
......@@ -8680,6 +8704,10 @@ class Symbol: public Name {
const char* PrivateSymbolToName() const;
#if TRACE_MAPS
friend class Name; // For PrivateSymbolToName.
#endif
DISALLOW_IMPLICIT_CONSTRUCTORS(Symbol);
};
......
......@@ -2083,7 +2083,8 @@ static MaybeHandle<Object> DebugEvaluate(Isolate* isolate,
static Handle<JSObject> NewJSObjectWithNullProto(Isolate* isolate) {
Handle<JSObject> result =
isolate->factory()->NewJSObject(isolate->object_function());
Handle<Map> new_map = Map::Copy(Handle<Map>(result->map()));
Handle<Map> new_map =
Map::Copy(Handle<Map>(result->map()), "ObjectWithNullProto");
new_map->set_prototype(*isolate->factory()->null_value());
JSObject::MigrateToMap(result, new_map);
return result;
......
......@@ -109,7 +109,7 @@ MUST_USE_RESULT static MaybeHandle<Object> CreateObjectLiteralBoilerplate(
if (should_normalize) {
// TODO(verwaest): We might not want to ever normalize here.
JSObject::NormalizeProperties(boilerplate, KEEP_INOBJECT_PROPERTIES,
length / 2);
length / 2, "Boilerplate");
}
// TODO(verwaest): Support tracking representations in the boilerplate.
for (int index = 0; index < length; index += 2) {
......@@ -166,7 +166,8 @@ MUST_USE_RESULT static MaybeHandle<Object> CreateObjectLiteralBoilerplate(
// constant function properties.
if (should_transform && !has_function_literal) {
JSObject::MigrateSlowToFast(boilerplate,
boilerplate->map()->unused_property_fields());
boilerplate->map()->unused_property_fields(),
"FastLiteral");
}
return boilerplate;
......
......@@ -469,7 +469,7 @@ RUNTIME_FUNCTION(Runtime_DisableAccessChecks) {
bool needs_access_checks = old_map->is_access_check_needed();
if (needs_access_checks) {
// Copy map so it won't interfere constructor's initial map.
Handle<Map> new_map = Map::Copy(old_map);
Handle<Map> new_map = Map::Copy(old_map, "DisableAccessChecks");
new_map->set_is_access_check_needed(false);
JSObject::MigrateToMap(Handle<JSObject>::cast(object), new_map);
}
......@@ -484,7 +484,7 @@ RUNTIME_FUNCTION(Runtime_EnableAccessChecks) {
Handle<Map> old_map(object->map());
RUNTIME_ASSERT(!old_map->is_access_check_needed());
// Copy map so it won't interfere constructor's initial map.
Handle<Map> new_map = Map::Copy(old_map);
Handle<Map> new_map = Map::Copy(old_map, "EnableAccessChecks");
new_map->set_is_access_check_needed(true);
JSObject::MigrateToMap(object, new_map);
return isolate->heap()->undefined_value();
......@@ -499,7 +499,8 @@ RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) {
// Conservative upper limit to prevent fuzz tests from going OOM.
RUNTIME_ASSERT(properties <= 100000);
if (object->HasFastProperties() && !object->IsJSGlobalProxy()) {
JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties);
JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties,
"OptimizeForAdding");
}
return *object;
}
......@@ -1152,7 +1153,8 @@ RUNTIME_FUNCTION(Runtime_ToFastProperties) {
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
if (object->IsJSObject() && !object->IsGlobalObject()) {
JSObject::MigrateSlowToFast(Handle<JSObject>::cast(object), 0);
JSObject::MigrateSlowToFast(Handle<JSObject>::cast(object), 0,
"RuntimeToFastProperties");
}
return *object;
}
......@@ -1456,7 +1458,7 @@ RUNTIME_FUNCTION(Runtime_DefineAccessorPropertyUnchecked) {
bool fast = obj->HasFastProperties();
RETURN_FAILURE_ON_EXCEPTION(
isolate, JSObject::DefineAccessor(obj, name, getter, setter, attr));
if (fast) JSObject::MigrateSlowToFast(obj, 0);
if (fast) JSObject::MigrateSlowToFast(obj, 0, "RuntimeDefineAccessor");
return isolate->heap()->undefined_value();
}
......
......@@ -347,7 +347,7 @@ static Handle<JSObject> NewSloppyArguments(Isolate* isolate,
isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
parameter_map->set_map(isolate->heap()->sloppy_arguments_elements_map());
Handle<Map> map = Map::Copy(handle(result->map()));
Handle<Map> map = Map::Copy(handle(result->map()), "NewSloppyArguments");
map->set_elements_kind(SLOPPY_ARGUMENTS_ELEMENTS);
result->set_map(*map);
......
#!/usr/bin/env python
# Copyright 2014 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import sys
action = sys.argv[1]
if action in ["help", "-h", "--help"] or len(sys.argv) != 3:
print("Usage: %s <action> <inputfile>, where action can be: \n"
"help Print this message\n"
"plain Print ASCII tree to stdout\n"
"dot Print dot file to stdout\n"
"count Count most frequent transition reasons\n" % sys.argv[0])
sys.exit(0)
filename = sys.argv[2]
maps = {}
root_maps = []
transitions = {}
annotations = {}
class Map(object):
def __init__(self, pointer, origin):
self.pointer = pointer
self.origin = origin
def __str__(self):
return "%s (%s)" % (self.pointer, self.origin)
class Transition(object):
def __init__(self, from_map, to_map, reason):
self.from_map = from_map
self.to_map = to_map
self.reason = reason
def RegisterNewMap(raw_map):
if raw_map in annotations:
annotations[raw_map] += 1
else:
annotations[raw_map] = 0
return AnnotateExistingMap(raw_map)
def AnnotateExistingMap(raw_map):
return "%s_%d" % (raw_map, annotations[raw_map])
def AddMap(pointer, origin):
pointer = RegisterNewMap(pointer)
maps[pointer] = Map(pointer, origin)
return pointer
def AddTransition(from_map, to_map, reason):
from_map = AnnotateExistingMap(from_map)
to_map = AnnotateExistingMap(to_map)
if from_map not in transitions:
transitions[from_map] = {}
targets = transitions[from_map]
if to_map in targets:
# Some events get printed twice, that's OK. In some cases, ignore the
# second output...
old_reason = targets[to_map].reason
if old_reason.startswith("ReplaceDescriptors"):
return
# ...and in others use it for additional detail.
if reason in []:
targets[to_map].reason = reason
return
# Unexpected duplicate events? Warn.
print("// warning: already have a transition from %s to %s, reason: %s" %
(from_map, to_map, targets[to_map].reason))
return
targets[to_map] = Transition(from_map, to_map, reason)
with open(filename, "r") as f:
last_to_map = ""
for line in f:
if not line.startswith("[TraceMaps: "): continue
words = line.split(" ")
event = words[1]
if event == "InitialMap":
assert words[2] == "map="
assert words[4] == "SFI="
new_map = AddMap(words[3], "SFI#%s" % words[5])
root_maps.append(new_map)
continue
if words[2] == "from=" and words[4] == "to=":
from_map = words[3]
to_map = words[5]
if from_map not in annotations:
print("// warning: unknown from_map %s" % from_map)
new_map = AddMap(from_map, "<unknown>")
root_maps.append(new_map)
if to_map != last_to_map:
AddMap(to_map, "<transition> (%s)" % event)
last_to_map = to_map
if event in ["Transition", "NoTransition"]:
assert words[6] == "name=", line
reason = "%s: %s" % (event, words[7])
elif event in ["Normalize", "ReplaceDescriptors", "SlowToFast"]:
assert words[6] == "reason=", line
reason = "%s: %s" % (event, words[7])
if words[8].strip() != "]":
reason = "%s_%s" % (reason, words[8])
else:
reason = event
AddTransition(from_map, to_map, reason)
continue
def PlainPrint(m, indent, label):
print("%s%s (%s)" % (indent, m, label))
if m in transitions:
for t in transitions[m]:
PlainPrint(t, indent + " ", transitions[m][t].reason)
def CountTransitions(m):
if m not in transitions: return 0
return len(transitions[m])
def DotPrint(m, label):
print("m%s [label=\"%s\"]" % (m[2:], label))
if m in transitions:
for t in transitions[m]:
# GraphViz doesn't like node labels looking like numbers, so use
# "m..." instead of "0x...".
print("m%s -> m%s" % (m[2:], t[2:]))
reason = transitions[m][t].reason
reason = reason.replace("\\", "BACKSLASH")
reason = reason.replace("\"", "\\\"")
DotPrint(t, reason)
if action == "plain":
root_maps = sorted(root_maps, key=CountTransitions, reverse=True)
for m in root_maps:
PlainPrint(m, "", maps[m].origin)
elif action == "dot":
print("digraph g {")
for m in root_maps:
DotPrint(m, maps[m].origin)
print("}")
elif action == "count":
reasons = {}
for s in transitions:
for t in transitions[s]:
reason = transitions[s][t].reason
if reason not in reasons:
reasons[reason] = 1
else:
reasons[reason] += 1
reasons_list = []
for r in reasons:
reasons_list.append("%8d %s" % (reasons[r], r))
reasons_list.sort(reverse=True)
for r in reasons_list[:20]:
print r
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