Commit af02c033 authored by ishell's avatar ishell Committed by Commit bot

[runtime] Record runtime call stats for Map::TransitionTo*Property,...

[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}
parent 61b49b3c
...@@ -1017,6 +1017,7 @@ v8_source_set("v8_base") { ...@@ -1017,6 +1017,7 @@ v8_source_set("v8_base") {
"src/conversions-inl.h", "src/conversions-inl.h",
"src/conversions.cc", "src/conversions.cc",
"src/conversions.h", "src/conversions.h",
"src/counters-inl.h",
"src/counters.cc", "src/counters.cc",
"src/counters.h", "src/counters.h",
"src/crankshaft/compilation-phase.cc", "src/crankshaft/compilation-phase.cc",
......
// 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, ...@@ -300,6 +300,10 @@ void RuntimeCallStats::CorrectCurrentCounterId(Isolate* isolate,
void RuntimeCallStats::Print(std::ostream& os) { void RuntimeCallStats::Print(std::ostream& os) {
RuntimeCallStatEntries entries; 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); #define PRINT_COUNTER(name, nargs, ressize) entries.Add(&this->Runtime_##name);
FOR_EACH_INTRINSIC(PRINT_COUNTER) FOR_EACH_INTRINSIC(PRINT_COUNTER)
#undef PRINT_COUNTER #undef PRINT_COUNTER
...@@ -312,10 +316,6 @@ void RuntimeCallStats::Print(std::ostream& os) { ...@@ -312,10 +316,6 @@ void RuntimeCallStats::Print(std::ostream& os) {
FOR_EACH_HANDLER_COUNTER(PRINT_COUNTER) FOR_EACH_HANDLER_COUNTER(PRINT_COUNTER)
#undef PRINT_COUNTER #undef PRINT_COUNTER
entries.Add(&this->ExternalCallback);
entries.Add(&this->GC);
entries.Add(&this->UnexpectedStubMiss);
entries.Print(os); entries.Print(os);
} }
......
...@@ -520,6 +520,20 @@ class RuntimeCallTimer { ...@@ -520,6 +520,20 @@ class RuntimeCallTimer {
base::ElapsedTimer timer_; 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) \ #define FOR_EACH_HANDLER_COUNTER(V) \
V(IC_HandlerCacheHit) \ V(IC_HandlerCacheHit) \
V(KeyedLoadIC_LoadIndexedStringStub) \ V(KeyedLoadIC_LoadIndexedStringStub) \
...@@ -564,12 +578,10 @@ class RuntimeCallStats { ...@@ -564,12 +578,10 @@ class RuntimeCallStats {
public: public:
typedef RuntimeCallCounter RuntimeCallStats::*CounterId; typedef RuntimeCallCounter RuntimeCallStats::*CounterId;
// Dummy counter for the unexpected stub miss. #define CALL_RUNTIME_COUNTER(name) \
RuntimeCallCounter UnexpectedStubMiss = RuntimeCallCounter name = RuntimeCallCounter(#name);
RuntimeCallCounter("UnexpectedStubMiss"); FOR_EACH_MANUAL_COUNTER(CALL_RUNTIME_COUNTER)
// Counter for runtime callbacks into JavaScript. #undef CALL_RUNTIME_COUNTER
RuntimeCallCounter ExternalCallback = RuntimeCallCounter("ExternalCallback");
RuntimeCallCounter GC = RuntimeCallCounter("GC");
#define CALL_RUNTIME_COUNTER(name, nargs, ressize) \ #define CALL_RUNTIME_COUNTER(name, nargs, ressize) \
RuntimeCallCounter Runtime_##name = RuntimeCallCounter(#name); RuntimeCallCounter Runtime_##name = RuntimeCallCounter(#name);
FOR_EACH_INTRINSIC(CALL_RUNTIME_COUNTER) FOR_EACH_INTRINSIC(CALL_RUNTIME_COUNTER)
...@@ -622,13 +634,18 @@ class RuntimeCallStats { ...@@ -622,13 +634,18 @@ class RuntimeCallStats {
// the time of C++ scope. // the time of C++ scope.
class RuntimeCallTimerScope { class RuntimeCallTimerScope {
public: public:
inline explicit RuntimeCallTimerScope( inline RuntimeCallTimerScope(Isolate* isolate,
Isolate* isolate, RuntimeCallStats::CounterId counter_id) { RuntimeCallStats::CounterId counter_id) {
if (V8_UNLIKELY(FLAG_runtime_call_stats)) { if (V8_UNLIKELY(FLAG_runtime_call_stats)) {
isolate_ = isolate; isolate_ = isolate;
RuntimeCallStats::Enter(isolate_, &timer_, counter_id); 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() { inline ~RuntimeCallTimerScope() {
if (V8_UNLIKELY(FLAG_runtime_call_stats)) { if (V8_UNLIKELY(FLAG_runtime_call_stats)) {
RuntimeCallStats::Leave(isolate_, &timer_); RuntimeCallStats::Leave(isolate_, &timer_);
......
...@@ -352,9 +352,14 @@ void LookupIterator::Delete() { ...@@ -352,9 +352,14 @@ void LookupIterator::Delete() {
ElementsAccessor* accessor = object->GetElementsAccessor(); ElementsAccessor* accessor = object->GetElementsAccessor();
accessor->Delete(object, number_); accessor->Delete(object, number_);
} else { } else {
PropertyNormalizationMode mode = holder->map()->is_prototype_map() bool is_prototype_map = holder->map()->is_prototype_map();
? KEEP_INOBJECT_PROPERTIES RuntimeCallTimerScope stats_scope(
: CLEAR_INOBJECT_PROPERTIES; isolate_, is_prototype_map
? &RuntimeCallStats::PrototypeObject_DeleteProperty
: &RuntimeCallStats::Object_DeleteProperty);
PropertyNormalizationMode mode =
is_prototype_map ? KEEP_INOBJECT_PROPERTIES : CLEAR_INOBJECT_PROPERTIES;
if (holder->HasFastProperties()) { if (holder->HasFastProperties()) {
JSObject::NormalizeProperties(Handle<JSObject>::cast(holder), mode, 0, JSObject::NormalizeProperties(Handle<JSObject>::cast(holder), mode, 0,
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include "src/codegen.h" #include "src/codegen.h"
#include "src/compilation-dependencies.h" #include "src/compilation-dependencies.h"
#include "src/compiler.h" #include "src/compiler.h"
#include "src/counters-inl.h"
#include "src/counters.h"
#include "src/date.h" #include "src/date.h"
#include "src/debug/debug.h" #include "src/debug/debug.h"
#include "src/deoptimizer.h" #include "src/deoptimizer.h"
...@@ -9018,6 +9020,11 @@ Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name, ...@@ -9018,6 +9020,11 @@ Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name,
Handle<Object> value, Handle<Object> value,
PropertyAttributes attributes, PropertyAttributes attributes,
StoreFromKeyed store_mode) { StoreFromKeyed store_mode) {
RuntimeCallTimerScope stats_scope(
*map, map->is_prototype_map()
? &RuntimeCallStats::PrototypeMap_TransitionToDataProperty
: &RuntimeCallStats::Map_TransitionToDataProperty);
DCHECK(name->IsUniqueName()); DCHECK(name->IsUniqueName());
DCHECK(!map->is_dictionary_map()); DCHECK(!map->is_dictionary_map());
...@@ -9098,6 +9105,12 @@ Handle<Map> Map::TransitionToAccessorProperty(Isolate* isolate, Handle<Map> map, ...@@ -9098,6 +9105,12 @@ Handle<Map> Map::TransitionToAccessorProperty(Isolate* isolate, Handle<Map> map,
Handle<Object> getter, Handle<Object> getter,
Handle<Object> setter, Handle<Object> setter,
PropertyAttributes attributes) { 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. // At least one of the accessors needs to be a new value.
DCHECK(!getter->IsNull() || !setter->IsNull()); DCHECK(!getter->IsNull() || !setter->IsNull());
DCHECK(name->IsUniqueName()); DCHECK(name->IsUniqueName());
...@@ -11667,6 +11680,8 @@ Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map, ...@@ -11667,6 +11680,8 @@ Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map,
// static // static
void Map::SetPrototype(Handle<Map> map, Handle<Object> prototype, void Map::SetPrototype(Handle<Map> map, Handle<Object> prototype,
PrototypeOptimizationMode proto_mode) { PrototypeOptimizationMode proto_mode) {
RuntimeCallTimerScope stats_scope(*map, &RuntimeCallStats::Map_SetPrototype);
bool is_hidden = false; bool is_hidden = false;
if (prototype->IsJSObject()) { if (prototype->IsJSObject()) {
Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype); Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype);
......
...@@ -685,6 +685,7 @@ ...@@ -685,6 +685,7 @@
'conversions-inl.h', 'conversions-inl.h',
'conversions.cc', 'conversions.cc',
'conversions.h', 'conversions.h',
'counters-inl.h',
'counters.cc', 'counters.cc',
'counters.h', 'counters.h',
'crankshaft/compilation-phase.cc', 'crankshaft/compilation-phase.cc',
......
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