[Interpreter] Add Ignition statistics JavaScript extension.
This commit introduces IgnitionStatisticsExtension, which provides methods for accessing Ignition statistics and counters from JavaScript. The extension is registered when FLAG_ignition and FLAG_trace_ignition_dispatches are both enabled. For the moment, the only exposed function is getIgnitionDispatchCounters(), which allows to retrieve Ignition dispatch counters as a JavaScript object. BUG=v8:4899 LOG=N Review URL: https://codereview.chromium.org/1899133004 Cr-Commit-Position: refs/heads/master@{#35816}
This commit is contained in:
parent
612985b298
commit
905becd13b
2
BUILD.gn
2
BUILD.gn
@ -1065,6 +1065,8 @@ source_set("v8_base") {
|
|||||||
"src/extensions/free-buffer-extension.h",
|
"src/extensions/free-buffer-extension.h",
|
||||||
"src/extensions/gc-extension.cc",
|
"src/extensions/gc-extension.cc",
|
||||||
"src/extensions/gc-extension.h",
|
"src/extensions/gc-extension.h",
|
||||||
|
"src/extensions/ignition-statistics-extension.cc",
|
||||||
|
"src/extensions/ignition-statistics-extension.h",
|
||||||
"src/extensions/statistics-extension.cc",
|
"src/extensions/statistics-extension.cc",
|
||||||
"src/extensions/statistics-extension.h",
|
"src/extensions/statistics-extension.h",
|
||||||
"src/extensions/trigger-failure-extension.cc",
|
"src/extensions/trigger-failure-extension.cc",
|
||||||
|
@ -1075,7 +1075,7 @@ ExternalReference ExternalReference::interpreter_dispatch_table_address(
|
|||||||
ExternalReference ExternalReference::interpreter_dispatch_counters(
|
ExternalReference ExternalReference::interpreter_dispatch_counters(
|
||||||
Isolate* isolate) {
|
Isolate* isolate) {
|
||||||
return ExternalReference(
|
return ExternalReference(
|
||||||
isolate->interpreter()->bytecode_dispatch_count_table());
|
isolate->interpreter()->bytecode_dispatch_counters_table());
|
||||||
}
|
}
|
||||||
|
|
||||||
ExternalReference::ExternalReference(StatsCounter* counter)
|
ExternalReference::ExternalReference(StatsCounter* counter)
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "src/extensions/externalize-string-extension.h"
|
#include "src/extensions/externalize-string-extension.h"
|
||||||
#include "src/extensions/free-buffer-extension.h"
|
#include "src/extensions/free-buffer-extension.h"
|
||||||
#include "src/extensions/gc-extension.h"
|
#include "src/extensions/gc-extension.h"
|
||||||
|
#include "src/extensions/ignition-statistics-extension.h"
|
||||||
#include "src/extensions/statistics-extension.h"
|
#include "src/extensions/statistics-extension.h"
|
||||||
#include "src/extensions/trigger-failure-extension.h"
|
#include "src/extensions/trigger-failure-extension.h"
|
||||||
#include "src/heap/heap.h"
|
#include "src/heap/heap.h"
|
||||||
@ -73,7 +74,7 @@ v8::Extension* Bootstrapper::gc_extension_ = NULL;
|
|||||||
v8::Extension* Bootstrapper::externalize_string_extension_ = NULL;
|
v8::Extension* Bootstrapper::externalize_string_extension_ = NULL;
|
||||||
v8::Extension* Bootstrapper::statistics_extension_ = NULL;
|
v8::Extension* Bootstrapper::statistics_extension_ = NULL;
|
||||||
v8::Extension* Bootstrapper::trigger_failure_extension_ = NULL;
|
v8::Extension* Bootstrapper::trigger_failure_extension_ = NULL;
|
||||||
|
v8::Extension* Bootstrapper::ignition_statistics_extension_ = NULL;
|
||||||
|
|
||||||
void Bootstrapper::InitializeOncePerProcess() {
|
void Bootstrapper::InitializeOncePerProcess() {
|
||||||
free_buffer_extension_ = new FreeBufferExtension;
|
free_buffer_extension_ = new FreeBufferExtension;
|
||||||
@ -86,6 +87,8 @@ void Bootstrapper::InitializeOncePerProcess() {
|
|||||||
v8::RegisterExtension(statistics_extension_);
|
v8::RegisterExtension(statistics_extension_);
|
||||||
trigger_failure_extension_ = new TriggerFailureExtension;
|
trigger_failure_extension_ = new TriggerFailureExtension;
|
||||||
v8::RegisterExtension(trigger_failure_extension_);
|
v8::RegisterExtension(trigger_failure_extension_);
|
||||||
|
ignition_statistics_extension_ = new IgnitionStatisticsExtension;
|
||||||
|
v8::RegisterExtension(ignition_statistics_extension_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -100,6 +103,8 @@ void Bootstrapper::TearDownExtensions() {
|
|||||||
statistics_extension_ = NULL;
|
statistics_extension_ = NULL;
|
||||||
delete trigger_failure_extension_;
|
delete trigger_failure_extension_;
|
||||||
trigger_failure_extension_ = NULL;
|
trigger_failure_extension_ = NULL;
|
||||||
|
delete ignition_statistics_extension_;
|
||||||
|
ignition_statistics_extension_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3209,17 +3214,20 @@ bool Genesis::InstallExtensions(Handle<Context> native_context,
|
|||||||
Isolate* isolate = native_context->GetIsolate();
|
Isolate* isolate = native_context->GetIsolate();
|
||||||
ExtensionStates extension_states; // All extensions have state UNVISITED.
|
ExtensionStates extension_states; // All extensions have state UNVISITED.
|
||||||
return InstallAutoExtensions(isolate, &extension_states) &&
|
return InstallAutoExtensions(isolate, &extension_states) &&
|
||||||
(!FLAG_expose_free_buffer ||
|
(!FLAG_expose_free_buffer ||
|
||||||
InstallExtension(isolate, "v8/free-buffer", &extension_states)) &&
|
InstallExtension(isolate, "v8/free-buffer", &extension_states)) &&
|
||||||
(!FLAG_expose_gc ||
|
(!FLAG_expose_gc ||
|
||||||
InstallExtension(isolate, "v8/gc", &extension_states)) &&
|
InstallExtension(isolate, "v8/gc", &extension_states)) &&
|
||||||
(!FLAG_expose_externalize_string ||
|
(!FLAG_expose_externalize_string ||
|
||||||
InstallExtension(isolate, "v8/externalize", &extension_states)) &&
|
InstallExtension(isolate, "v8/externalize", &extension_states)) &&
|
||||||
(!FLAG_track_gc_object_stats ||
|
(!FLAG_track_gc_object_stats ||
|
||||||
InstallExtension(isolate, "v8/statistics", &extension_states)) &&
|
InstallExtension(isolate, "v8/statistics", &extension_states)) &&
|
||||||
(!FLAG_expose_trigger_failure ||
|
(!FLAG_expose_trigger_failure ||
|
||||||
InstallExtension(isolate, "v8/trigger-failure", &extension_states)) &&
|
InstallExtension(isolate, "v8/trigger-failure", &extension_states)) &&
|
||||||
InstallRequestedExtensions(isolate, extensions, &extension_states);
|
(!(FLAG_ignition && FLAG_trace_ignition_dispatches) ||
|
||||||
|
InstallExtension(isolate, "v8/ignition-statistics",
|
||||||
|
&extension_states)) &&
|
||||||
|
InstallRequestedExtensions(isolate, extensions, &extension_states);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -136,6 +136,7 @@ class Bootstrapper final {
|
|||||||
static v8::Extension* externalize_string_extension_;
|
static v8::Extension* externalize_string_extension_;
|
||||||
static v8::Extension* statistics_extension_;
|
static v8::Extension* statistics_extension_;
|
||||||
static v8::Extension* trigger_failure_extension_;
|
static v8::Extension* trigger_failure_extension_;
|
||||||
|
static v8::Extension* ignition_statistics_extension_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(Bootstrapper);
|
DISALLOW_COPY_AND_ASSIGN(Bootstrapper);
|
||||||
};
|
};
|
||||||
|
28
src/d8.cc
28
src/d8.cc
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#ifndef V8_SHARED
|
#ifndef V8_SHARED
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <fstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#endif // !V8_SHARED
|
#endif // !V8_SHARED
|
||||||
|
|
||||||
@ -1276,6 +1277,21 @@ struct CounterAndKey {
|
|||||||
inline bool operator<(const CounterAndKey& lhs, const CounterAndKey& rhs) {
|
inline bool operator<(const CounterAndKey& lhs, const CounterAndKey& rhs) {
|
||||||
return strcmp(lhs.key, rhs.key) < 0;
|
return strcmp(lhs.key, rhs.key) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Shell::WriteIgnitionDispatchCountersFile(v8::Isolate* isolate) {
|
||||||
|
HandleScope handle_scope(isolate);
|
||||||
|
Local<Context> context = Context::New(isolate);
|
||||||
|
Context::Scope context_scope(context);
|
||||||
|
|
||||||
|
Local<Object> dispatch_counters = reinterpret_cast<i::Isolate*>(isolate)
|
||||||
|
->interpreter()
|
||||||
|
->GetDispatchCountersObject();
|
||||||
|
std::ofstream dispatch_counters_stream(
|
||||||
|
i::FLAG_trace_ignition_dispatches_output_file);
|
||||||
|
dispatch_counters_stream << *String::Utf8Value(
|
||||||
|
JSON::Stringify(context, dispatch_counters).ToLocalChecked());
|
||||||
|
}
|
||||||
|
|
||||||
#endif // !V8_SHARED
|
#endif // !V8_SHARED
|
||||||
|
|
||||||
|
|
||||||
@ -1314,12 +1330,6 @@ void Shell::OnExit(v8::Isolate* isolate) {
|
|||||||
delete [] counters;
|
delete [] counters;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i::FLAG_trace_ignition_dispatches) {
|
|
||||||
reinterpret_cast<i::Isolate*>(isolate)
|
|
||||||
->interpreter()
|
|
||||||
->WriteDispatchCounters();
|
|
||||||
}
|
|
||||||
|
|
||||||
delete counters_file_;
|
delete counters_file_;
|
||||||
delete counter_map_;
|
delete counter_map_;
|
||||||
#endif // !V8_SHARED
|
#endif // !V8_SHARED
|
||||||
@ -2484,6 +2494,12 @@ int Shell::Main(int argc, char* argv[]) {
|
|||||||
RunShell(isolate);
|
RunShell(isolate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef V8_SHARED
|
||||||
|
if (i::FLAG_ignition && i::FLAG_trace_ignition_dispatches) {
|
||||||
|
WriteIgnitionDispatchCountersFile(isolate);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Shut down contexts and collect garbage.
|
// Shut down contexts and collect garbage.
|
||||||
evaluation_context_.Reset();
|
evaluation_context_.Reset();
|
||||||
#ifndef V8_SHARED
|
#ifndef V8_SHARED
|
||||||
|
1
src/d8.h
1
src/d8.h
@ -461,6 +461,7 @@ class Shell : public i::AllStatic {
|
|||||||
static i::List<Worker*> workers_;
|
static i::List<Worker*> workers_;
|
||||||
static i::List<SharedArrayBuffer::Contents> externalized_shared_contents_;
|
static i::List<SharedArrayBuffer::Contents> externalized_shared_contents_;
|
||||||
|
|
||||||
|
static void WriteIgnitionDispatchCountersFile(v8::Isolate* isolate);
|
||||||
static Counter* GetCounter(const char* name, bool is_histogram);
|
static Counter* GetCounter(const char* name, bool is_histogram);
|
||||||
static Local<String> Stringify(Isolate* isolate, Local<Value> value);
|
static Local<String> Stringify(Isolate* isolate, Local<Value> value);
|
||||||
#endif // !V8_SHARED
|
#endif // !V8_SHARED
|
||||||
|
36
src/extensions/ignition-statistics-extension.cc
Normal file
36
src/extensions/ignition-statistics-extension.cc
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#include "src/extensions/ignition-statistics-extension.h"
|
||||||
|
|
||||||
|
#include "src/interpreter/bytecodes.h"
|
||||||
|
#include "src/interpreter/interpreter.h"
|
||||||
|
#include "src/isolate.h"
|
||||||
|
|
||||||
|
namespace v8 {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
v8::Local<v8::FunctionTemplate>
|
||||||
|
IgnitionStatisticsExtension::GetNativeFunctionTemplate(
|
||||||
|
v8::Isolate* isolate, v8::Local<v8::String> name) {
|
||||||
|
DCHECK_EQ(strcmp(*v8::String::Utf8Value(name), "getIgnitionDispatchCounters"),
|
||||||
|
0);
|
||||||
|
return v8::FunctionTemplate::New(
|
||||||
|
isolate, IgnitionStatisticsExtension::GetIgnitionDispatchCounters);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* const IgnitionStatisticsExtension::kSource =
|
||||||
|
"native function getIgnitionDispatchCounters();";
|
||||||
|
|
||||||
|
void IgnitionStatisticsExtension::GetIgnitionDispatchCounters(
|
||||||
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||||
|
DCHECK_EQ(args.Length(), 0);
|
||||||
|
DCHECK(FLAG_trace_ignition_dispatches);
|
||||||
|
args.GetReturnValue().Set(reinterpret_cast<Isolate*>(args.GetIsolate())
|
||||||
|
->interpreter()
|
||||||
|
->GetDispatchCountersObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace v8
|
31
src/extensions/ignition-statistics-extension.h
Normal file
31
src/extensions/ignition-statistics-extension.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// 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_EXTENSIONS_IGNITION_STATISTICS_EXTENSION_H_
|
||||||
|
#define V8_EXTENSIONS_IGNITION_STATISTICS_EXTENSION_H_
|
||||||
|
|
||||||
|
#include "include/v8.h"
|
||||||
|
|
||||||
|
namespace v8 {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
class IgnitionStatisticsExtension : public v8::Extension {
|
||||||
|
public:
|
||||||
|
IgnitionStatisticsExtension()
|
||||||
|
: v8::Extension("v8/ignition-statistics", kSource) {}
|
||||||
|
|
||||||
|
v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
|
||||||
|
v8::Isolate* isolate, v8::Local<v8::String> name) override;
|
||||||
|
|
||||||
|
static void GetIgnitionDispatchCounters(
|
||||||
|
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const char* const kSource;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace v8
|
||||||
|
|
||||||
|
#endif // V8_EXTENSIONS_IGNITION_STATISTICS_EXTENSION_H_
|
@ -38,9 +38,9 @@ void Interpreter::Initialize() {
|
|||||||
|
|
||||||
if (FLAG_trace_ignition_dispatches) {
|
if (FLAG_trace_ignition_dispatches) {
|
||||||
static const int kBytecodeCount = static_cast<int>(Bytecode::kLast) + 1;
|
static const int kBytecodeCount = static_cast<int>(Bytecode::kLast) + 1;
|
||||||
bytecode_dispatch_count_table_.Reset(
|
bytecode_dispatch_counters_table_.Reset(
|
||||||
new uintptr_t[kBytecodeCount * kBytecodeCount]);
|
new uintptr_t[kBytecodeCount * kBytecodeCount]);
|
||||||
memset(bytecode_dispatch_count_table_.get(), 0,
|
memset(bytecode_dispatch_counters_table_.get(), 0,
|
||||||
sizeof(uintptr_t) * kBytecodeCount * kBytecodeCount);
|
sizeof(uintptr_t) * kBytecodeCount * kBytecodeCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,9 +201,18 @@ const char* Interpreter::LookupNameOfBytecodeHandler(Code* code) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::WriteDispatchCounters() {
|
uintptr_t Interpreter::GetDispatchCounter(Bytecode from, Bytecode to) const {
|
||||||
std::ofstream stream(FLAG_trace_ignition_dispatches_output_file);
|
int from_index = Bytecodes::ToByte(from);
|
||||||
static const int kBytecodeCount = static_cast<int>(Bytecode::kLast) + 1;
|
int to_index = Bytecodes::ToByte(to);
|
||||||
|
return bytecode_dispatch_counters_table_[from_index * kNumberOfBytecodes +
|
||||||
|
to_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
Local<v8::Object> Interpreter::GetDispatchCountersObject() {
|
||||||
|
v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(isolate_);
|
||||||
|
Local<v8::Context> context = isolate->GetCurrentContext();
|
||||||
|
|
||||||
|
Local<v8::Object> counters_map = v8::Object::New(isolate);
|
||||||
|
|
||||||
// Output is a JSON-encoded object of objects.
|
// Output is a JSON-encoded object of objects.
|
||||||
//
|
//
|
||||||
@ -216,35 +225,36 @@ void Interpreter::WriteDispatchCounters() {
|
|||||||
// object is always present, even if the value is empty because all counters
|
// object is always present, even if the value is empty because all counters
|
||||||
// for that source are zero.
|
// for that source are zero.
|
||||||
|
|
||||||
stream << '{';
|
for (int from_index = 0; from_index < kNumberOfBytecodes; ++from_index) {
|
||||||
|
|
||||||
for (int from_index = 0; from_index < kBytecodeCount; ++from_index) {
|
|
||||||
if (from_index > 0) stream << ",\n ";
|
|
||||||
|
|
||||||
Bytecode from_bytecode = Bytecodes::FromByte(from_index);
|
Bytecode from_bytecode = Bytecodes::FromByte(from_index);
|
||||||
stream << "\"" << Bytecodes::ToString(from_bytecode) << "\": {";
|
Local<v8::Object> counters_row = v8::Object::New(isolate);
|
||||||
|
|
||||||
|
for (int to_index = 0; to_index < kNumberOfBytecodes; ++to_index) {
|
||||||
|
Bytecode to_bytecode = Bytecodes::FromByte(to_index);
|
||||||
|
uintptr_t counter = GetDispatchCounter(from_bytecode, to_bytecode);
|
||||||
|
|
||||||
bool emitted_first = false;
|
|
||||||
for (int to_index = 0; to_index < kBytecodeCount; ++to_index) {
|
|
||||||
uintptr_t counter =
|
|
||||||
bytecode_dispatch_count_table_[from_index * kBytecodeCount +
|
|
||||||
to_index];
|
|
||||||
if (counter > 0) {
|
if (counter > 0) {
|
||||||
if (emitted_first) {
|
std::string to_name = Bytecodes::ToString(to_bytecode);
|
||||||
stream << ", ";
|
Local<v8::String> to_name_object =
|
||||||
} else {
|
v8::String::NewFromUtf8(isolate, to_name.c_str(),
|
||||||
emitted_first = true;
|
NewStringType::kNormal)
|
||||||
}
|
.ToLocalChecked();
|
||||||
|
Local<v8::Number> counter_object = v8::Number::New(isolate, counter);
|
||||||
Bytecode to_bytecode = Bytecodes::FromByte(to_index);
|
CHECK(counters_row->Set(context, to_name_object, counter_object)
|
||||||
stream << '"' << Bytecodes::ToString(to_bytecode) << "\": " << counter;
|
.IsJust());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stream << "}";
|
std::string from_name = Bytecodes::ToString(from_bytecode);
|
||||||
|
Local<v8::String> from_name_object =
|
||||||
|
v8::String::NewFromUtf8(isolate, from_name.c_str(),
|
||||||
|
NewStringType::kNormal)
|
||||||
|
.ToLocalChecked();
|
||||||
|
|
||||||
|
CHECK(counters_map->Set(context, from_name_object, counters_row).IsJust());
|
||||||
}
|
}
|
||||||
|
|
||||||
stream << '}';
|
return counters_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
// LdaZero
|
// LdaZero
|
||||||
|
@ -53,14 +53,14 @@ class Interpreter {
|
|||||||
void TraceCodegen(Handle<Code> code);
|
void TraceCodegen(Handle<Code> code);
|
||||||
const char* LookupNameOfBytecodeHandler(Code* code);
|
const char* LookupNameOfBytecodeHandler(Code* code);
|
||||||
|
|
||||||
void WriteDispatchCounters();
|
Local<v8::Object> GetDispatchCountersObject();
|
||||||
|
|
||||||
Address dispatch_table_address() {
|
Address dispatch_table_address() {
|
||||||
return reinterpret_cast<Address>(&dispatch_table_[0]);
|
return reinterpret_cast<Address>(&dispatch_table_[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t* bytecode_dispatch_count_table() {
|
Address bytecode_dispatch_counters_table() {
|
||||||
return bytecode_dispatch_count_table_.get();
|
return reinterpret_cast<Address>(bytecode_dispatch_counters_table_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -143,6 +143,8 @@ class Interpreter {
|
|||||||
void DoStoreLookupSlot(LanguageMode language_mode,
|
void DoStoreLookupSlot(LanguageMode language_mode,
|
||||||
InterpreterAssembler* assembler);
|
InterpreterAssembler* assembler);
|
||||||
|
|
||||||
|
uintptr_t GetDispatchCounter(Bytecode from, Bytecode to) const;
|
||||||
|
|
||||||
// Get dispatch table index of bytecode.
|
// Get dispatch table index of bytecode.
|
||||||
static size_t GetDispatchTableIndex(Bytecode bytecode,
|
static size_t GetDispatchTableIndex(Bytecode bytecode,
|
||||||
OperandScale operand_scale);
|
OperandScale operand_scale);
|
||||||
@ -151,10 +153,11 @@ class Interpreter {
|
|||||||
|
|
||||||
static const int kNumberOfWideVariants = 3;
|
static const int kNumberOfWideVariants = 3;
|
||||||
static const int kDispatchTableSize = kNumberOfWideVariants * (kMaxUInt8 + 1);
|
static const int kDispatchTableSize = kNumberOfWideVariants * (kMaxUInt8 + 1);
|
||||||
|
static const int kNumberOfBytecodes = static_cast<int>(Bytecode::kLast) + 1;
|
||||||
|
|
||||||
Isolate* isolate_;
|
Isolate* isolate_;
|
||||||
Address dispatch_table_[kDispatchTableSize];
|
Address dispatch_table_[kDispatchTableSize];
|
||||||
v8::base::SmartArrayPointer<uintptr_t> bytecode_dispatch_count_table_;
|
v8::base::SmartArrayPointer<uintptr_t> bytecode_dispatch_counters_table_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(Interpreter);
|
DISALLOW_COPY_AND_ASSIGN(Interpreter);
|
||||||
};
|
};
|
||||||
|
@ -775,6 +775,8 @@
|
|||||||
'extensions/free-buffer-extension.h',
|
'extensions/free-buffer-extension.h',
|
||||||
'extensions/gc-extension.cc',
|
'extensions/gc-extension.cc',
|
||||||
'extensions/gc-extension.h',
|
'extensions/gc-extension.h',
|
||||||
|
'extensions/ignition-statistics-extension.cc',
|
||||||
|
'extensions/ignition-statistics-extension.h',
|
||||||
'extensions/statistics-extension.cc',
|
'extensions/statistics-extension.cc',
|
||||||
'extensions/statistics-extension.h',
|
'extensions/statistics-extension.h',
|
||||||
'extensions/trigger-failure-extension.cc',
|
'extensions/trigger-failure-extension.cc',
|
||||||
|
62
test/mjsunit/ignition/ignition-statistics-extension.js
Normal file
62
test/mjsunit/ignition/ignition-statistics-extension.js
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
// Flags: --ignition --trace-ignition-dispatches
|
||||||
|
|
||||||
|
assertEquals(typeof getIgnitionDispatchCounters, "function");
|
||||||
|
|
||||||
|
var old_dispatch_counters = getIgnitionDispatchCounters();
|
||||||
|
|
||||||
|
// Check that old_dispatch_counters is a non-empty object of objects, such that
|
||||||
|
// the value of each property in the inner objects is a number.
|
||||||
|
|
||||||
|
assertEquals(typeof old_dispatch_counters, "object");
|
||||||
|
assertTrue(Object.getOwnPropertyNames(old_dispatch_counters).length > 0);
|
||||||
|
for (var source_bytecode in old_dispatch_counters) {
|
||||||
|
var counters_row = old_dispatch_counters[source_bytecode];
|
||||||
|
assertEquals(typeof counters_row, "object");
|
||||||
|
for (var counter in counters_row) {
|
||||||
|
assertEquals(typeof counters_row[counter], "number");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do something
|
||||||
|
function f(x) { return x*x; }
|
||||||
|
f(42);
|
||||||
|
|
||||||
|
var new_dispatch_counters = getIgnitionDispatchCounters();
|
||||||
|
|
||||||
|
var old_source_bytecodes = Object.getOwnPropertyNames(old_dispatch_counters);
|
||||||
|
var new_source_bytecodes = Object.getOwnPropertyNames(new_dispatch_counters);
|
||||||
|
var common_source_bytecodes = new_source_bytecodes.filter(function (name) {
|
||||||
|
return old_source_bytecodes.indexOf(name) > -1;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check that the keys on the outer objects are the same
|
||||||
|
assertEquals(common_source_bytecodes, old_source_bytecodes);
|
||||||
|
assertEquals(common_source_bytecodes, new_source_bytecodes);
|
||||||
|
|
||||||
|
common_source_bytecodes.forEach(function (source_bytecode) {
|
||||||
|
var new_counters_row = new_dispatch_counters[source_bytecode];
|
||||||
|
var old_counters_row = old_dispatch_counters[source_bytecode];
|
||||||
|
|
||||||
|
var old_destination_bytecodes = Object.getOwnPropertyNames(old_counters_row);
|
||||||
|
var new_destination_bytecodes = Object.getOwnPropertyNames(new_counters_row);
|
||||||
|
|
||||||
|
// Check that all the keys in old_ are in new_ too
|
||||||
|
old_destination_bytecodes.forEach(function (name) {
|
||||||
|
assertTrue(new_destination_bytecodes.indexOf(name) > -1);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check that for each source-destination pair, the counter has either
|
||||||
|
// appeared (was undefined before calling f()), is unchanged, or incremented.
|
||||||
|
new_destination_bytecodes.forEach(function (destination_bytecode) {
|
||||||
|
var new_counter = new_counters_row[destination_bytecode];
|
||||||
|
var old_counter = old_counters_row[destination_bytecode];
|
||||||
|
assertTrue(typeof new_counter === "number");
|
||||||
|
if (typeof old_counter === "number") {
|
||||||
|
assertTrue(new_counter >= old_counter);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user