[runtime] Record runtime call stats for Map::TransitionTo*Property, Map::SetPrototype and property deletion to separate buckets.
Review-Url: https://codereview.chromium.org/1973473002 Cr-Commit-Position: refs/heads/master@{#36176}
This commit is contained in:
parent
61b49b3c09
commit
af02c0336d
1
BUILD.gn
1
BUILD.gn
@ -1017,6 +1017,7 @@ v8_source_set("v8_base") {
|
||||
"src/conversions-inl.h",
|
||||
"src/conversions.cc",
|
||||
"src/conversions.h",
|
||||
"src/counters-inl.h",
|
||||
"src/counters.cc",
|
||||
"src/counters.h",
|
||||
"src/crankshaft/compilation-phase.cc",
|
||||
|
24
src/counters-inl.h
Normal file
24
src/counters-inl.h
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
#ifndef V8_COUNTERS_INL_H_
|
||||
#define V8_COUNTERS_INL_H_
|
||||
|
||||
#include "src/counters.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
RuntimeCallTimerScope::RuntimeCallTimerScope(
|
||||
HeapObject* heap_object, RuntimeCallStats::CounterId counter_id) {
|
||||
if (V8_UNLIKELY(FLAG_runtime_call_stats)) {
|
||||
isolate_ = heap_object->GetIsolate();
|
||||
RuntimeCallStats::Enter(isolate_, &timer_, counter_id);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_COUNTERS_INL_H_
|
@ -300,6 +300,10 @@ void RuntimeCallStats::CorrectCurrentCounterId(Isolate* isolate,
|
||||
void RuntimeCallStats::Print(std::ostream& os) {
|
||||
RuntimeCallStatEntries entries;
|
||||
|
||||
#define PRINT_COUNTER(name) entries.Add(&this->name);
|
||||
FOR_EACH_MANUAL_COUNTER(PRINT_COUNTER)
|
||||
#undef PRINT_COUNTER
|
||||
|
||||
#define PRINT_COUNTER(name, nargs, ressize) entries.Add(&this->Runtime_##name);
|
||||
FOR_EACH_INTRINSIC(PRINT_COUNTER)
|
||||
#undef PRINT_COUNTER
|
||||
@ -312,10 +316,6 @@ void RuntimeCallStats::Print(std::ostream& os) {
|
||||
FOR_EACH_HANDLER_COUNTER(PRINT_COUNTER)
|
||||
#undef PRINT_COUNTER
|
||||
|
||||
entries.Add(&this->ExternalCallback);
|
||||
entries.Add(&this->GC);
|
||||
entries.Add(&this->UnexpectedStubMiss);
|
||||
|
||||
entries.Print(os);
|
||||
}
|
||||
|
||||
|
@ -520,6 +520,20 @@ class RuntimeCallTimer {
|
||||
base::ElapsedTimer timer_;
|
||||
};
|
||||
|
||||
#define FOR_EACH_MANUAL_COUNTER(V) \
|
||||
/* Counter for runtime callbacks into JavaScript. */ \
|
||||
V(ExternalCallback) \
|
||||
V(GC) \
|
||||
/* Dummy counter for the unexpected stub miss. */ \
|
||||
V(UnexpectedStubMiss) \
|
||||
V(PrototypeMap_TransitionToAccessorProperty) \
|
||||
V(PrototypeMap_TransitionToDataProperty) \
|
||||
V(Map_TransitionToAccessorProperty) \
|
||||
V(Map_TransitionToDataProperty) \
|
||||
V(Map_SetPrototype) \
|
||||
V(PrototypeObject_DeleteProperty) \
|
||||
V(Object_DeleteProperty)
|
||||
|
||||
#define FOR_EACH_HANDLER_COUNTER(V) \
|
||||
V(IC_HandlerCacheHit) \
|
||||
V(KeyedLoadIC_LoadIndexedStringStub) \
|
||||
@ -564,12 +578,10 @@ class RuntimeCallStats {
|
||||
public:
|
||||
typedef RuntimeCallCounter RuntimeCallStats::*CounterId;
|
||||
|
||||
// Dummy counter for the unexpected stub miss.
|
||||
RuntimeCallCounter UnexpectedStubMiss =
|
||||
RuntimeCallCounter("UnexpectedStubMiss");
|
||||
// Counter for runtime callbacks into JavaScript.
|
||||
RuntimeCallCounter ExternalCallback = RuntimeCallCounter("ExternalCallback");
|
||||
RuntimeCallCounter GC = RuntimeCallCounter("GC");
|
||||
#define CALL_RUNTIME_COUNTER(name) \
|
||||
RuntimeCallCounter name = RuntimeCallCounter(#name);
|
||||
FOR_EACH_MANUAL_COUNTER(CALL_RUNTIME_COUNTER)
|
||||
#undef CALL_RUNTIME_COUNTER
|
||||
#define CALL_RUNTIME_COUNTER(name, nargs, ressize) \
|
||||
RuntimeCallCounter Runtime_##name = RuntimeCallCounter(#name);
|
||||
FOR_EACH_INTRINSIC(CALL_RUNTIME_COUNTER)
|
||||
@ -622,13 +634,18 @@ class RuntimeCallStats {
|
||||
// the time of C++ scope.
|
||||
class RuntimeCallTimerScope {
|
||||
public:
|
||||
inline explicit RuntimeCallTimerScope(
|
||||
Isolate* isolate, RuntimeCallStats::CounterId counter_id) {
|
||||
inline RuntimeCallTimerScope(Isolate* isolate,
|
||||
RuntimeCallStats::CounterId counter_id) {
|
||||
if (V8_UNLIKELY(FLAG_runtime_call_stats)) {
|
||||
isolate_ = isolate;
|
||||
RuntimeCallStats::Enter(isolate_, &timer_, counter_id);
|
||||
}
|
||||
}
|
||||
// This constructor is here just to avoid calling GetIsolate() when the
|
||||
// stats are disabled and the isolate is not directly available.
|
||||
inline RuntimeCallTimerScope(HeapObject* heap_object,
|
||||
RuntimeCallStats::CounterId counter_id);
|
||||
|
||||
inline ~RuntimeCallTimerScope() {
|
||||
if (V8_UNLIKELY(FLAG_runtime_call_stats)) {
|
||||
RuntimeCallStats::Leave(isolate_, &timer_);
|
||||
|
@ -352,9 +352,14 @@ void LookupIterator::Delete() {
|
||||
ElementsAccessor* accessor = object->GetElementsAccessor();
|
||||
accessor->Delete(object, number_);
|
||||
} else {
|
||||
PropertyNormalizationMode mode = holder->map()->is_prototype_map()
|
||||
? KEEP_INOBJECT_PROPERTIES
|
||||
: CLEAR_INOBJECT_PROPERTIES;
|
||||
bool is_prototype_map = holder->map()->is_prototype_map();
|
||||
RuntimeCallTimerScope stats_scope(
|
||||
isolate_, is_prototype_map
|
||||
? &RuntimeCallStats::PrototypeObject_DeleteProperty
|
||||
: &RuntimeCallStats::Object_DeleteProperty);
|
||||
|
||||
PropertyNormalizationMode mode =
|
||||
is_prototype_map ? KEEP_INOBJECT_PROPERTIES : CLEAR_INOBJECT_PROPERTIES;
|
||||
|
||||
if (holder->HasFastProperties()) {
|
||||
JSObject::NormalizeProperties(Handle<JSObject>::cast(holder), mode, 0,
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include "src/codegen.h"
|
||||
#include "src/compilation-dependencies.h"
|
||||
#include "src/compiler.h"
|
||||
#include "src/counters-inl.h"
|
||||
#include "src/counters.h"
|
||||
#include "src/date.h"
|
||||
#include "src/debug/debug.h"
|
||||
#include "src/deoptimizer.h"
|
||||
@ -9018,6 +9020,11 @@ Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name,
|
||||
Handle<Object> value,
|
||||
PropertyAttributes attributes,
|
||||
StoreFromKeyed store_mode) {
|
||||
RuntimeCallTimerScope stats_scope(
|
||||
*map, map->is_prototype_map()
|
||||
? &RuntimeCallStats::PrototypeMap_TransitionToDataProperty
|
||||
: &RuntimeCallStats::Map_TransitionToDataProperty);
|
||||
|
||||
DCHECK(name->IsUniqueName());
|
||||
DCHECK(!map->is_dictionary_map());
|
||||
|
||||
@ -9098,6 +9105,12 @@ Handle<Map> Map::TransitionToAccessorProperty(Isolate* isolate, Handle<Map> map,
|
||||
Handle<Object> getter,
|
||||
Handle<Object> setter,
|
||||
PropertyAttributes attributes) {
|
||||
RuntimeCallTimerScope stats_scope(
|
||||
isolate,
|
||||
map->is_prototype_map()
|
||||
? &RuntimeCallStats::PrototypeMap_TransitionToAccessorProperty
|
||||
: &RuntimeCallStats::Map_TransitionToAccessorProperty);
|
||||
|
||||
// At least one of the accessors needs to be a new value.
|
||||
DCHECK(!getter->IsNull() || !setter->IsNull());
|
||||
DCHECK(name->IsUniqueName());
|
||||
@ -11667,6 +11680,8 @@ Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map,
|
||||
// static
|
||||
void Map::SetPrototype(Handle<Map> map, Handle<Object> prototype,
|
||||
PrototypeOptimizationMode proto_mode) {
|
||||
RuntimeCallTimerScope stats_scope(*map, &RuntimeCallStats::Map_SetPrototype);
|
||||
|
||||
bool is_hidden = false;
|
||||
if (prototype->IsJSObject()) {
|
||||
Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype);
|
||||
|
@ -685,6 +685,7 @@
|
||||
'conversions-inl.h',
|
||||
'conversions.cc',
|
||||
'conversions.h',
|
||||
'counters-inl.h',
|
||||
'counters.cc',
|
||||
'counters.h',
|
||||
'crankshaft/compilation-phase.cc',
|
||||
|
Loading…
Reference in New Issue
Block a user