[inspector] Remove Type Profiler
See https://docs.google.com/document/d/1dJHFRXKE4NUchvYweuyzsolXDEWACr-jJZEPyC6f9EQ/edit?usp=sharing Change-Id: Ie5b30db30d55ba701a336d8a59dbff7771276e96 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3936281 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Maya Lekova <mslekova@chromium.org> Commit-Queue: Marja Hölttä <marja@chromium.org> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Cr-Commit-Position: refs/heads/main@{#83593}
This commit is contained in:
parent
4e2ecbd2d7
commit
283791d250
@ -1270,8 +1270,6 @@ filegroup(
|
||||
"src/debug/debug-scopes.h",
|
||||
"src/debug/debug-stack-trace-iterator.cc",
|
||||
"src/debug/debug-stack-trace-iterator.h",
|
||||
"src/debug/debug-type-profile.cc",
|
||||
"src/debug/debug-type-profile.h",
|
||||
"src/debug/debug.cc",
|
||||
"src/debug/debug.h",
|
||||
"src/debug/interface-types.h",
|
||||
|
2
BUILD.gn
2
BUILD.gn
@ -2949,7 +2949,6 @@ v8_header_set("v8_internal_headers") {
|
||||
"src/debug/debug-scope-iterator.h",
|
||||
"src/debug/debug-scopes.h",
|
||||
"src/debug/debug-stack-trace-iterator.h",
|
||||
"src/debug/debug-type-profile.h",
|
||||
"src/debug/debug.h",
|
||||
"src/debug/interface-types.h",
|
||||
"src/debug/liveedit-diff.h",
|
||||
@ -4373,7 +4372,6 @@ v8_source_set("v8_base_without_compiler") {
|
||||
"src/debug/debug-scope-iterator.cc",
|
||||
"src/debug/debug-scopes.cc",
|
||||
"src/debug/debug-stack-trace-iterator.cc",
|
||||
"src/debug/debug-type-profile.cc",
|
||||
"src/debug/debug.cc",
|
||||
"src/debug/liveedit-diff.cc",
|
||||
"src/debug/liveedit.cc",
|
||||
|
@ -946,34 +946,6 @@
|
||||
{ "name": "url", "type": "string", "description": "JavaScript script name or url." },
|
||||
{ "name": "functions", "type": "array", "items": { "$ref": "FunctionCoverage" }, "description": "Functions contained in the script that has coverage data." }
|
||||
]
|
||||
},
|
||||
{ "id": "TypeObject",
|
||||
"type": "object",
|
||||
"description": "Describes a type collected during runtime.",
|
||||
"properties": [
|
||||
{ "name": "name", "type": "string", "description": "Name of a type collected with type profiling." }
|
||||
],
|
||||
"experimental": true
|
||||
},
|
||||
{ "id": "TypeProfileEntry",
|
||||
"type": "object",
|
||||
"description": "Source offset and types for a parameter or return value.",
|
||||
"properties": [
|
||||
{ "name": "offset", "type": "integer", "description": "Source offset of the parameter or end of function for return values." },
|
||||
{ "name": "types", "type": "array", "items": {"$ref": "TypeObject"}, "description": "The types for this parameter or return value."}
|
||||
],
|
||||
"experimental": true
|
||||
},
|
||||
{
|
||||
"id": "ScriptTypeProfile",
|
||||
"type": "object",
|
||||
"description": "Type profile data collected during runtime for a JavaScript script.",
|
||||
"properties": [
|
||||
{ "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "JavaScript script id." },
|
||||
{ "name": "url", "type": "string", "description": "JavaScript script name or url." },
|
||||
{ "name": "entries", "type": "array", "items": { "$ref": "TypeProfileEntry" }, "description": "Type profile entries for parameters and return values of the functions in the script." }
|
||||
],
|
||||
"experimental": true
|
||||
}
|
||||
],
|
||||
"commands": [
|
||||
@ -1024,24 +996,6 @@
|
||||
{ "name": "result", "type": "array", "items": { "$ref": "ScriptCoverage" }, "description": "Coverage data for the current isolate." }
|
||||
],
|
||||
"description": "Collect coverage data for the current isolate. The coverage data may be incomplete due to garbage collection."
|
||||
},
|
||||
{
|
||||
"name": "startTypeProfile",
|
||||
"description": "Enable type profile.",
|
||||
"experimental": true
|
||||
},
|
||||
{
|
||||
"name": "stopTypeProfile",
|
||||
"description": "Disable type profile. Disabling releases type profile data collected so far.",
|
||||
"experimental": true
|
||||
},
|
||||
{
|
||||
"name": "takeTypeProfile",
|
||||
"returns": [
|
||||
{ "name": "result", "type": "array", "items": { "$ref": "ScriptTypeProfile" }, "description": "Type profile for all scripts since startTypeProfile() was turned on." }
|
||||
],
|
||||
"description": "Collect type profile.",
|
||||
"experimental": true
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
|
@ -918,30 +918,6 @@ domain Profiler
|
||||
# Functions contained in the script that has coverage data.
|
||||
array of FunctionCoverage functions
|
||||
|
||||
# Describes a type collected during runtime.
|
||||
experimental type TypeObject extends object
|
||||
properties
|
||||
# Name of a type collected with type profiling.
|
||||
string name
|
||||
|
||||
# Source offset and types for a parameter or return value.
|
||||
experimental type TypeProfileEntry extends object
|
||||
properties
|
||||
# Source offset of the parameter or end of function for return values.
|
||||
integer offset
|
||||
# The types for this parameter or return value.
|
||||
array of TypeObject types
|
||||
|
||||
# Type profile data collected during runtime for a JavaScript script.
|
||||
experimental type ScriptTypeProfile extends object
|
||||
properties
|
||||
# JavaScript script id.
|
||||
Runtime.ScriptId scriptId
|
||||
# JavaScript script name or url.
|
||||
string url
|
||||
# Type profile entries for parameters and return values of the functions in the script.
|
||||
array of TypeProfileEntry entries
|
||||
|
||||
command disable
|
||||
|
||||
command enable
|
||||
@ -976,9 +952,6 @@ domain Profiler
|
||||
# Monotonically increasing time (in seconds) when the coverage update was taken in the backend.
|
||||
number timestamp
|
||||
|
||||
# Enable type profile.
|
||||
experimental command startTypeProfile
|
||||
|
||||
command stop
|
||||
returns
|
||||
# Recorded profile.
|
||||
@ -988,9 +961,6 @@ domain Profiler
|
||||
# executing optimized code.
|
||||
command stopPreciseCoverage
|
||||
|
||||
# Disable type profile. Disabling releases type profile data collected so far.
|
||||
experimental command stopTypeProfile
|
||||
|
||||
# Collect coverage data for the current isolate, and resets execution counters. Precise code
|
||||
# coverage needs to have started.
|
||||
command takePreciseCoverage
|
||||
@ -1000,12 +970,6 @@ domain Profiler
|
||||
# Monotonically increasing time (in seconds) when the coverage update was taken in the backend.
|
||||
number timestamp
|
||||
|
||||
# Collect type profile.
|
||||
experimental command takeTypeProfile
|
||||
returns
|
||||
# Type profile for all scripts since startTypeProfile() was turned on.
|
||||
array of ScriptTypeProfile result
|
||||
|
||||
event consoleProfileFinished
|
||||
parameters
|
||||
string id
|
||||
|
@ -967,14 +967,6 @@ void BaselineCompiler::VisitDefineKeyedOwnPropertyInLiteral() {
|
||||
IndexAsTagged(3)); // slot
|
||||
}
|
||||
|
||||
void BaselineCompiler::VisitCollectTypeProfile() {
|
||||
SaveAccumulatorScope accumulator_scope(&basm_);
|
||||
CallRuntime(Runtime::kCollectTypeProfile,
|
||||
IntAsSmi(0), // position
|
||||
kInterpreterAccumulatorRegister, // value
|
||||
FeedbackVector()); // feedback vector
|
||||
}
|
||||
|
||||
void BaselineCompiler::VisitAdd() {
|
||||
CallBuiltin<Builtin::kAdd_Baseline>(
|
||||
RegisterOperand(0), kInterpreterAccumulatorRegister, Index(1));
|
||||
|
@ -3282,8 +3282,6 @@ MaybeHandle<SharedFunctionInfo> CompileScriptOnMainThread(
|
||||
if (!maybe_script.ToHandle(&script)) {
|
||||
script = NewScript(isolate, &parse_info, source, script_details, natives);
|
||||
}
|
||||
DCHECK_IMPLIES(parse_info.flags().collect_type_profile(),
|
||||
script->IsUserJavaScript());
|
||||
DCHECK_EQ(parse_info.flags().is_repl_mode(), script->is_repl_mode());
|
||||
|
||||
return Compiler::CompileToplevel(&parse_info, script, isolate,
|
||||
|
@ -1672,20 +1672,6 @@ void BytecodeGraphBuilder::VisitDefineKeyedOwnPropertyInLiteral() {
|
||||
environment()->RecordAfterState(node, Environment::kAttachFrameState);
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitCollectTypeProfile() {
|
||||
PrepareEagerCheckpoint();
|
||||
|
||||
Node* position =
|
||||
jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0));
|
||||
Node* value = environment()->LookupAccumulator();
|
||||
Node* vector = jsgraph()->Constant(feedback_vector());
|
||||
|
||||
const Operator* op = javascript()->CallRuntime(Runtime::kCollectTypeProfile);
|
||||
|
||||
Node* node = NewNode(op, position, value, vector);
|
||||
environment()->RecordAfterState(node, Environment::kAttachFrameState);
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitLdaContextSlot() {
|
||||
const Operator* op = javascript()->LoadContext(
|
||||
bytecode_iterator().GetUnsignedImmediateOperand(2),
|
||||
|
@ -605,9 +605,8 @@ std::unique_ptr<Coverage> Coverage::CollectPrecise(Isolate* isolate) {
|
||||
DCHECK(!isolate->is_best_effort_code_coverage());
|
||||
std::unique_ptr<Coverage> result =
|
||||
Collect(isolate, isolate->code_coverage_mode());
|
||||
if (!isolate->is_collecting_type_profile() &&
|
||||
(isolate->is_precise_binary_code_coverage() ||
|
||||
isolate->is_block_binary_code_coverage())) {
|
||||
if (isolate->is_precise_binary_code_coverage() ||
|
||||
isolate->is_block_binary_code_coverage()) {
|
||||
// We do not have to hold onto feedback vectors for invocations we already
|
||||
// reported. So we can reset the list.
|
||||
isolate->SetFeedbackVectorsForProfilingTools(
|
||||
@ -766,10 +765,8 @@ void Coverage::SelectMode(Isolate* isolate, debug::CoverageMode mode) {
|
||||
// following coverage recording (without reloads) will be at function
|
||||
// granularity.
|
||||
isolate->debug()->RemoveAllCoverageInfos();
|
||||
if (!isolate->is_collecting_type_profile()) {
|
||||
isolate->SetFeedbackVectorsForProfilingTools(
|
||||
ReadOnlyRoots(isolate).undefined_value());
|
||||
}
|
||||
isolate->SetFeedbackVectorsForProfilingTools(
|
||||
ReadOnlyRoots(isolate).undefined_value());
|
||||
break;
|
||||
case debug::CoverageMode::kBlockBinary:
|
||||
case debug::CoverageMode::kBlockCount:
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include "src/debug/debug-evaluate.h"
|
||||
#include "src/debug/debug-property-iterator.h"
|
||||
#include "src/debug/debug-stack-trace-iterator.h"
|
||||
#include "src/debug/debug-type-profile.h"
|
||||
#include "src/debug/debug.h"
|
||||
#include "src/execution/vm-state-inl.h"
|
||||
#include "src/heap/heap.h"
|
||||
@ -1317,48 +1316,6 @@ void Coverage::SelectMode(Isolate* isolate, CoverageMode mode) {
|
||||
i::Coverage::SelectMode(reinterpret_cast<i::Isolate*>(isolate), mode);
|
||||
}
|
||||
|
||||
int TypeProfile::Entry::SourcePosition() const { return entry_->position; }
|
||||
|
||||
std::vector<MaybeLocal<String>> TypeProfile::Entry::Types() const {
|
||||
std::vector<MaybeLocal<String>> result;
|
||||
for (const internal::Handle<internal::String>& type : entry_->types) {
|
||||
result.emplace_back(ToApiHandle<String>(type));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
TypeProfile::ScriptData::ScriptData(
|
||||
size_t index, std::shared_ptr<i::TypeProfile> type_profile)
|
||||
: script_(&type_profile->at(index)),
|
||||
type_profile_(std::move(type_profile)) {}
|
||||
|
||||
Local<Script> TypeProfile::ScriptData::GetScript() const {
|
||||
return ToApiHandle<Script>(script_->script);
|
||||
}
|
||||
|
||||
std::vector<TypeProfile::Entry> TypeProfile::ScriptData::Entries() const {
|
||||
std::vector<TypeProfile::Entry> result;
|
||||
for (const internal::TypeProfileEntry& entry : script_->entries) {
|
||||
result.push_back(TypeProfile::Entry(&entry, type_profile_));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
TypeProfile TypeProfile::Collect(Isolate* isolate) {
|
||||
return TypeProfile(
|
||||
i::TypeProfile::Collect(reinterpret_cast<i::Isolate*>(isolate)));
|
||||
}
|
||||
|
||||
void TypeProfile::SelectMode(Isolate* isolate, TypeProfileMode mode) {
|
||||
i::TypeProfile::SelectMode(reinterpret_cast<i::Isolate*>(isolate), mode);
|
||||
}
|
||||
|
||||
size_t TypeProfile::ScriptCount() const { return type_profile_->size(); }
|
||||
|
||||
TypeProfile::ScriptData TypeProfile::GetScriptData(size_t i) const {
|
||||
return ScriptData(i, type_profile_);
|
||||
}
|
||||
|
||||
MaybeLocal<v8::Value> EphemeronTable::Get(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> key) {
|
||||
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
|
||||
|
@ -34,13 +34,10 @@ namespace internal {
|
||||
struct CoverageBlock;
|
||||
struct CoverageFunction;
|
||||
struct CoverageScript;
|
||||
struct TypeProfileEntry;
|
||||
struct TypeProfileScript;
|
||||
class Coverage;
|
||||
class DisableBreak;
|
||||
class PostponeInterruptsScope;
|
||||
class Script;
|
||||
class TypeProfile;
|
||||
} // namespace internal
|
||||
|
||||
namespace debug {
|
||||
@ -438,64 +435,6 @@ class V8_EXPORT_PRIVATE Coverage {
|
||||
std::shared_ptr<i::Coverage> coverage_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Provide API layer between inspector and type profile.
|
||||
*/
|
||||
class V8_EXPORT_PRIVATE TypeProfile {
|
||||
public:
|
||||
MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(TypeProfile);
|
||||
|
||||
class ScriptData; // Forward declaration.
|
||||
|
||||
class V8_EXPORT_PRIVATE Entry {
|
||||
public:
|
||||
MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(Entry);
|
||||
|
||||
int SourcePosition() const;
|
||||
std::vector<MaybeLocal<String>> Types() const;
|
||||
|
||||
private:
|
||||
explicit Entry(const i::TypeProfileEntry* entry,
|
||||
std::shared_ptr<i::TypeProfile> type_profile)
|
||||
: entry_(entry), type_profile_(std::move(type_profile)) {}
|
||||
|
||||
const i::TypeProfileEntry* entry_;
|
||||
std::shared_ptr<i::TypeProfile> type_profile_;
|
||||
|
||||
friend class v8::debug::TypeProfile::ScriptData;
|
||||
};
|
||||
|
||||
class V8_EXPORT_PRIVATE ScriptData {
|
||||
public:
|
||||
MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(ScriptData);
|
||||
|
||||
Local<debug::Script> GetScript() const;
|
||||
std::vector<Entry> Entries() const;
|
||||
|
||||
private:
|
||||
explicit ScriptData(size_t index,
|
||||
std::shared_ptr<i::TypeProfile> type_profile);
|
||||
|
||||
i::TypeProfileScript* script_;
|
||||
std::shared_ptr<i::TypeProfile> type_profile_;
|
||||
|
||||
friend class v8::debug::TypeProfile;
|
||||
};
|
||||
|
||||
static TypeProfile Collect(Isolate* isolate);
|
||||
|
||||
static void SelectMode(Isolate* isolate, TypeProfileMode mode);
|
||||
|
||||
size_t ScriptCount() const;
|
||||
ScriptData GetScriptData(size_t i) const;
|
||||
|
||||
private:
|
||||
explicit TypeProfile(std::shared_ptr<i::TypeProfile> type_profile)
|
||||
: type_profile_(std::move(type_profile)) {}
|
||||
|
||||
std::shared_ptr<i::TypeProfile> type_profile_;
|
||||
};
|
||||
|
||||
class V8_EXPORT_PRIVATE ScopeIterator {
|
||||
public:
|
||||
static std::unique_ptr<ScopeIterator> CreateForFunction(
|
||||
|
@ -1,121 +0,0 @@
|
||||
// Copyright 2017 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/debug/debug-type-profile.h"
|
||||
|
||||
#include "src/execution/isolate.h"
|
||||
#include "src/objects/feedback-vector.h"
|
||||
#include "src/objects/objects-inl.h"
|
||||
#include "src/objects/objects.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
std::unique_ptr<TypeProfile> TypeProfile::Collect(Isolate* isolate) {
|
||||
std::unique_ptr<TypeProfile> result(new TypeProfile());
|
||||
|
||||
// Feedback vectors are already listed to prevent losing them to GC.
|
||||
DCHECK(isolate->factory()
|
||||
->feedback_vectors_for_profiling_tools()
|
||||
->IsArrayList());
|
||||
Handle<ArrayList> list = Handle<ArrayList>::cast(
|
||||
isolate->factory()->feedback_vectors_for_profiling_tools());
|
||||
|
||||
Script::Iterator scripts(isolate);
|
||||
|
||||
for (Script script = scripts.Next(); !script.is_null();
|
||||
script = scripts.Next()) {
|
||||
if (!script.IsUserJavaScript()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Handle<Script> script_handle(script, isolate);
|
||||
|
||||
TypeProfileScript type_profile_script(script_handle);
|
||||
std::vector<TypeProfileEntry>* entries = &type_profile_script.entries;
|
||||
|
||||
// TODO(franzih): Sort the vectors by script first instead of iterating
|
||||
// the list multiple times.
|
||||
for (int i = 0; i < list->Length(); i++) {
|
||||
FeedbackVector vector = FeedbackVector::cast(list->Get(i));
|
||||
SharedFunctionInfo info = vector.shared_function_info();
|
||||
DCHECK(info.IsSubjectToDebugging());
|
||||
|
||||
// Match vectors with script.
|
||||
if (script != info.script()) {
|
||||
continue;
|
||||
}
|
||||
if (!info.HasFeedbackMetadata() || info.feedback_metadata().is_empty() ||
|
||||
!info.feedback_metadata().HasTypeProfileSlot()) {
|
||||
continue;
|
||||
}
|
||||
FeedbackSlot slot = vector.GetTypeProfileSlot();
|
||||
FeedbackNexus nexus(vector, slot);
|
||||
std::vector<int> source_positions = nexus.GetSourcePositions();
|
||||
for (int position : source_positions) {
|
||||
DCHECK_GE(position, 0);
|
||||
entries->emplace_back(position, nexus.GetTypesForSourcePositions(
|
||||
static_cast<uint32_t>(position)));
|
||||
}
|
||||
|
||||
// Releases type profile data collected so far.
|
||||
nexus.ResetTypeProfile();
|
||||
}
|
||||
if (!entries->empty()) {
|
||||
result->emplace_back(type_profile_script);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void TypeProfile::SelectMode(Isolate* isolate, debug::TypeProfileMode mode) {
|
||||
if (mode != isolate->type_profile_mode()) {
|
||||
// Changing the type profile mode can change the bytecode that would be
|
||||
// generated for a function, which can interfere with lazy source positions,
|
||||
// so just force source position collection whenever there's such a change.
|
||||
isolate->CollectSourcePositionsForAllBytecodeArrays();
|
||||
}
|
||||
|
||||
HandleScope handle_scope(isolate);
|
||||
|
||||
if (mode == debug::TypeProfileMode::kNone) {
|
||||
if (!isolate->factory()
|
||||
->feedback_vectors_for_profiling_tools()
|
||||
->IsUndefined(isolate)) {
|
||||
// Release type profile data collected so far.
|
||||
|
||||
// Feedback vectors are already listed to prevent losing them to GC.
|
||||
DCHECK(isolate->factory()
|
||||
->feedback_vectors_for_profiling_tools()
|
||||
->IsArrayList());
|
||||
Handle<ArrayList> list = Handle<ArrayList>::cast(
|
||||
isolate->factory()->feedback_vectors_for_profiling_tools());
|
||||
|
||||
for (int i = 0; i < list->Length(); i++) {
|
||||
FeedbackVector vector = FeedbackVector::cast(list->Get(i));
|
||||
SharedFunctionInfo info = vector.shared_function_info();
|
||||
DCHECK(info.IsSubjectToDebugging());
|
||||
if (info.feedback_metadata().HasTypeProfileSlot()) {
|
||||
FeedbackSlot slot = vector.GetTypeProfileSlot();
|
||||
FeedbackNexus nexus(vector, slot);
|
||||
nexus.ResetTypeProfile();
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the feedback vectors from the list if they're not used by code
|
||||
// coverage.
|
||||
if (isolate->is_best_effort_code_coverage()) {
|
||||
isolate->SetFeedbackVectorsForProfilingTools(
|
||||
ReadOnlyRoots(isolate).undefined_value());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DCHECK_EQ(debug::TypeProfileMode::kCollect, mode);
|
||||
isolate->MaybeInitializeVectorListFromHeap();
|
||||
}
|
||||
isolate->set_type_profile_mode(mode);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
@ -1,46 +0,0 @@
|
||||
// Copyright 2017 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_DEBUG_DEBUG_TYPE_PROFILE_H_
|
||||
#define V8_DEBUG_DEBUG_TYPE_PROFILE_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "src/debug/debug-interface.h"
|
||||
#include "src/handles/handles.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
// Forward declaration.
|
||||
class Isolate;
|
||||
|
||||
struct TypeProfileEntry {
|
||||
explicit TypeProfileEntry(
|
||||
int pos, std::vector<v8::internal::Handle<internal::String>> t)
|
||||
: position(pos), types(std::move(t)) {}
|
||||
int position;
|
||||
std::vector<v8::internal::Handle<internal::String>> types;
|
||||
};
|
||||
|
||||
struct TypeProfileScript {
|
||||
explicit TypeProfileScript(Handle<Script> s) : script(s) {}
|
||||
Handle<Script> script;
|
||||
std::vector<TypeProfileEntry> entries;
|
||||
};
|
||||
|
||||
class TypeProfile : public std::vector<TypeProfileScript> {
|
||||
public:
|
||||
static std::unique_ptr<TypeProfile> Collect(Isolate* isolate);
|
||||
static void SelectMode(Isolate* isolate, debug::TypeProfileMode mode);
|
||||
|
||||
private:
|
||||
TypeProfile() = default;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_DEBUG_DEBUG_TYPE_PROFILE_H_
|
@ -78,11 +78,6 @@ enum class CoverageMode {
|
||||
kBlockBinary,
|
||||
};
|
||||
|
||||
enum class TypeProfileMode {
|
||||
kNone,
|
||||
kCollect,
|
||||
};
|
||||
|
||||
class V8_EXPORT_PRIVATE BreakLocation : public Location {
|
||||
public:
|
||||
BreakLocation(int line_number, int column_number, BreakLocationType type)
|
||||
|
@ -1333,7 +1333,6 @@ void FeedbackNexus::Print(std::ostream& os) {
|
||||
break;
|
||||
}
|
||||
case FeedbackSlotKind::kLiteral:
|
||||
case FeedbackSlotKind::kTypeProfile:
|
||||
break;
|
||||
case FeedbackSlotKind::kJumpLoop:
|
||||
os << "JumpLoop";
|
||||
|
@ -529,7 +529,6 @@ using DebugObjectCache = std::vector<Handle<HeapObject>>;
|
||||
V(bool, formatting_stack_trace, false) \
|
||||
/* Perform side effect checks on function call and API callbacks. */ \
|
||||
V(DebugInfo::ExecutionMode, debug_execution_mode, DebugInfo::kBreakpoints) \
|
||||
V(debug::TypeProfileMode, type_profile_mode, debug::TypeProfileMode::kNone) \
|
||||
V(bool, disable_bytecode_flushing, false) \
|
||||
V(int, last_console_context_id, 0) \
|
||||
V(v8_inspector::V8Inspector*, inspector, nullptr) \
|
||||
@ -1431,10 +1430,6 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
|
||||
return is_precise_count_code_coverage() || is_block_count_code_coverage();
|
||||
}
|
||||
|
||||
bool is_collecting_type_profile() const {
|
||||
return type_profile_mode() == debug::TypeProfileMode::kCollect;
|
||||
}
|
||||
|
||||
// Collect feedback vectors with data for code coverage or type profile.
|
||||
// Reset the list, when both code coverage and type profile are not
|
||||
// needed anymore. This keeps many feedback vectors alive, but code
|
||||
|
@ -60,11 +60,6 @@ int LocalIsolate::GetNextUniqueSharedFunctionInfoId() {
|
||||
}
|
||||
#endif // V8_SFI_HAS_UNIQUE_ID
|
||||
|
||||
bool LocalIsolate::is_collecting_type_profile() const {
|
||||
// TODO(leszeks): Figure out if it makes sense to check this asynchronously.
|
||||
return isolate_->is_collecting_type_profile();
|
||||
}
|
||||
|
||||
// Used for lazy initialization, based on an assumption that most
|
||||
// LocalIsolates won't be used to parse any BigInt literals.
|
||||
void LocalIsolate::InitializeBigIntProcessor() {
|
||||
|
@ -106,8 +106,6 @@ class V8_EXPORT_PRIVATE LocalIsolate final : private HiddenLocalFactory {
|
||||
int GetNextUniqueSharedFunctionInfoId();
|
||||
#endif // V8_SFI_HAS_UNIQUE_ID
|
||||
|
||||
bool is_collecting_type_profile() const;
|
||||
|
||||
// TODO(cbruni): rename this back to logger() once the V8FileLogger
|
||||
// refactoring is completed.
|
||||
LocalLogger* v8_file_logger() const { return logger_.get(); }
|
||||
|
@ -28,7 +28,6 @@ static const char preciseCoverageCallCount[] = "preciseCoverageCallCount";
|
||||
static const char preciseCoverageDetailed[] = "preciseCoverageDetailed";
|
||||
static const char preciseCoverageAllowTriggeredUpdates[] =
|
||||
"preciseCoverageAllowTriggeredUpdates";
|
||||
static const char typeProfileStarted[] = "typeProfileStarted";
|
||||
} // namespace ProfilerAgentState
|
||||
|
||||
namespace {
|
||||
@ -450,80 +449,6 @@ Response V8ProfilerAgentImpl::getBestEffortCoverage(
|
||||
return coverageToProtocol(m_session->inspector(), coverage, out_result);
|
||||
}
|
||||
|
||||
namespace {
|
||||
std::unique_ptr<protocol::Array<protocol::Profiler::ScriptTypeProfile>>
|
||||
typeProfileToProtocol(V8InspectorImpl* inspector,
|
||||
const v8::debug::TypeProfile& type_profile) {
|
||||
auto result = std::make_unique<
|
||||
protocol::Array<protocol::Profiler::ScriptTypeProfile>>();
|
||||
v8::Isolate* isolate = inspector->isolate();
|
||||
for (size_t i = 0; i < type_profile.ScriptCount(); i++) {
|
||||
v8::debug::TypeProfile::ScriptData script_data =
|
||||
type_profile.GetScriptData(i);
|
||||
v8::Local<v8::debug::Script> script = script_data.GetScript();
|
||||
auto entries = std::make_unique<
|
||||
protocol::Array<protocol::Profiler::TypeProfileEntry>>();
|
||||
|
||||
for (const auto& entry : script_data.Entries()) {
|
||||
auto types =
|
||||
std::make_unique<protocol::Array<protocol::Profiler::TypeObject>>();
|
||||
for (const auto& type : entry.Types()) {
|
||||
types->emplace_back(
|
||||
protocol::Profiler::TypeObject::create()
|
||||
.setName(toProtocolString(
|
||||
isolate, type.FromMaybe(v8::Local<v8::String>())))
|
||||
.build());
|
||||
}
|
||||
entries->emplace_back(protocol::Profiler::TypeProfileEntry::create()
|
||||
.setOffset(entry.SourcePosition())
|
||||
.setTypes(std::move(types))
|
||||
.build());
|
||||
}
|
||||
String16 url;
|
||||
v8::Local<v8::String> name;
|
||||
if (script->SourceURL().ToLocal(&name) && name->Length()) {
|
||||
url = toProtocolString(isolate, name);
|
||||
} else if (script->Name().ToLocal(&name) && name->Length()) {
|
||||
url = resourceNameToUrl(inspector, name);
|
||||
}
|
||||
result->emplace_back(protocol::Profiler::ScriptTypeProfile::create()
|
||||
.setScriptId(String16::fromInteger(script->Id()))
|
||||
.setUrl(url)
|
||||
.setEntries(std::move(entries))
|
||||
.build());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
Response V8ProfilerAgentImpl::startTypeProfile() {
|
||||
m_state->setBoolean(ProfilerAgentState::typeProfileStarted, true);
|
||||
v8::debug::TypeProfile::SelectMode(m_isolate,
|
||||
v8::debug::TypeProfileMode::kCollect);
|
||||
return Response::Success();
|
||||
}
|
||||
|
||||
Response V8ProfilerAgentImpl::stopTypeProfile() {
|
||||
m_state->setBoolean(ProfilerAgentState::typeProfileStarted, false);
|
||||
v8::debug::TypeProfile::SelectMode(m_isolate,
|
||||
v8::debug::TypeProfileMode::kNone);
|
||||
return Response::Success();
|
||||
}
|
||||
|
||||
Response V8ProfilerAgentImpl::takeTypeProfile(
|
||||
std::unique_ptr<protocol::Array<protocol::Profiler::ScriptTypeProfile>>*
|
||||
out_result) {
|
||||
if (!m_state->booleanProperty(ProfilerAgentState::typeProfileStarted,
|
||||
false)) {
|
||||
return Response::ServerError("Type profile has not been started.");
|
||||
}
|
||||
v8::HandleScope handle_scope(m_isolate);
|
||||
v8::debug::TypeProfile type_profile =
|
||||
v8::debug::TypeProfile::Collect(m_isolate);
|
||||
*out_result = typeProfileToProtocol(m_session->inspector(), type_profile);
|
||||
return Response::Success();
|
||||
}
|
||||
|
||||
String16 V8ProfilerAgentImpl::nextProfileId() {
|
||||
return String16::fromInteger(
|
||||
v8::base::Relaxed_AtomicIncrement(&s_lastProfileId, 1));
|
||||
|
@ -53,12 +53,6 @@ class V8ProfilerAgentImpl : public protocol::Profiler::Backend {
|
||||
std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>>*
|
||||
out_result) override;
|
||||
|
||||
Response startTypeProfile() override;
|
||||
Response stopTypeProfile() override;
|
||||
Response takeTypeProfile(
|
||||
std::unique_ptr<protocol::Array<protocol::Profiler::ScriptTypeProfile>>*
|
||||
out_result) override;
|
||||
|
||||
void consoleProfile(const String16& title);
|
||||
void consoleProfileEnd(const String16& title);
|
||||
|
||||
|
@ -881,11 +881,6 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::DefineKeyedOwnPropertyInLiteral(
|
||||
return *this;
|
||||
}
|
||||
|
||||
BytecodeArrayBuilder& BytecodeArrayBuilder::CollectTypeProfile(int position) {
|
||||
OutputCollectTypeProfile(position);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BytecodeArrayBuilder& BytecodeArrayBuilder::SetNamedProperty(
|
||||
Register object, size_t name_index, int feedback_slot,
|
||||
LanguageMode language_mode) {
|
||||
|
@ -158,10 +158,6 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final {
|
||||
Register object, Register name,
|
||||
DefineKeyedOwnPropertyInLiteralFlags flags, int feedback_slot);
|
||||
|
||||
// Collect type information for developer tools. The value for which we
|
||||
// record the type is stored in the accumulator.
|
||||
BytecodeArrayBuilder& CollectTypeProfile(int position);
|
||||
|
||||
// Set a property named by a property name, trigger the setters and
|
||||
// set traps if necessary. The value to be set should be in the
|
||||
// accumulator.
|
||||
|
@ -1423,17 +1423,6 @@ void BytecodeGenerator::GenerateBytecodeBody() {
|
||||
// Emit tracing call if requested to do so.
|
||||
if (v8_flags.trace) builder()->CallRuntime(Runtime::kTraceEnter);
|
||||
|
||||
// Emit type profile call.
|
||||
if (info()->flags().collect_type_profile()) {
|
||||
feedback_spec()->AddTypeProfileSlot();
|
||||
int num_parameters = closure_scope()->num_parameters();
|
||||
for (int i = 0; i < num_parameters; i++) {
|
||||
Register parameter(builder()->Parameter(i));
|
||||
builder()->LoadAccumulatorWithRegister(parameter).CollectTypeProfile(
|
||||
closure_scope()->parameter(i)->initializer_position());
|
||||
}
|
||||
}
|
||||
|
||||
// Increment the function-scope block coverage counter.
|
||||
BuildIncrementBlockCoverageCounterIfEnabled(literal, SourceRangeKind::kBody);
|
||||
|
||||
@ -3686,9 +3675,6 @@ void BytecodeGenerator::BuildReturn(int source_position) {
|
||||
builder()->StoreAccumulatorInRegister(result).CallRuntime(
|
||||
Runtime::kTraceExit, result);
|
||||
}
|
||||
if (info()->flags().collect_type_profile()) {
|
||||
builder()->CollectTypeProfile(info()->literal()->return_position());
|
||||
}
|
||||
builder()->SetStatementPosition(source_position);
|
||||
builder()->Return();
|
||||
}
|
||||
|
@ -157,8 +157,6 @@ namespace interpreter {
|
||||
V(DefineKeyedOwnPropertyInLiteral, ImplicitRegisterUse::kReadAccumulator, \
|
||||
OperandType::kReg, OperandType::kReg, OperandType::kFlag8, \
|
||||
OperandType::kIdx) \
|
||||
V(CollectTypeProfile, ImplicitRegisterUse::kReadAccumulator, \
|
||||
OperandType::kImm) \
|
||||
\
|
||||
/* Binary Operators */ \
|
||||
V(Add, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg, \
|
||||
|
@ -743,18 +743,6 @@ IGNITION_HANDLER(DefineKeyedOwnPropertyInLiteral, InterpreterAssembler) {
|
||||
Dispatch();
|
||||
}
|
||||
|
||||
IGNITION_HANDLER(CollectTypeProfile, InterpreterAssembler) {
|
||||
TNode<Smi> position = BytecodeOperandImmSmi(0);
|
||||
TNode<Object> value = GetAccumulator();
|
||||
|
||||
TNode<HeapObject> feedback_vector = LoadFeedbackVector();
|
||||
TNode<Context> context = GetContext();
|
||||
|
||||
CallRuntime(Runtime::kCollectTypeProfile, context, position, value,
|
||||
feedback_vector);
|
||||
Dispatch();
|
||||
}
|
||||
|
||||
// LdaModuleVariable <cell_index> <depth>
|
||||
//
|
||||
// Load the contents of a module variable into the accumulator. The variable is
|
||||
|
@ -1895,14 +1895,6 @@ void MaglevGraphBuilder::VisitDefineKeyedOwnPropertyInLiteral() {
|
||||
{object, name, value, flags, feedback_vector, slot}));
|
||||
}
|
||||
|
||||
void MaglevGraphBuilder::VisitCollectTypeProfile() {
|
||||
ValueNode* position = GetSmiConstant(GetFlag8Operand(0));
|
||||
ValueNode* value = GetAccumulatorTagged();
|
||||
ValueNode* feedback_vector = GetConstant(feedback());
|
||||
SetAccumulator(BuildCallRuntime(Runtime::kCollectTypeProfile,
|
||||
{position, value, feedback_vector}));
|
||||
}
|
||||
|
||||
void MaglevGraphBuilder::VisitAdd() { VisitBinaryOperation<Operation::kAdd>(); }
|
||||
void MaglevGraphBuilder::VisitSub() {
|
||||
VisitBinaryOperation<Operation::kSubtract>();
|
||||
|
@ -70,7 +70,6 @@ int FeedbackMetadata::GetSlotSize(FeedbackSlotKind kind) {
|
||||
case FeedbackSlotKind::kCompareOp:
|
||||
case FeedbackSlotKind::kBinaryOp:
|
||||
case FeedbackSlotKind::kLiteral:
|
||||
case FeedbackSlotKind::kTypeProfile:
|
||||
case FeedbackSlotKind::kJumpLoop:
|
||||
return 1;
|
||||
|
||||
|
@ -31,20 +31,6 @@ FeedbackSlot FeedbackVectorSpec::AddSlot(FeedbackSlotKind kind) {
|
||||
return FeedbackSlot(slot);
|
||||
}
|
||||
|
||||
FeedbackSlot FeedbackVectorSpec::AddTypeProfileSlot() {
|
||||
FeedbackSlot slot = AddSlot(FeedbackSlotKind::kTypeProfile);
|
||||
CHECK_EQ(FeedbackVectorSpec::kTypeProfileSlotIndex,
|
||||
FeedbackVector::GetIndex(slot));
|
||||
return slot;
|
||||
}
|
||||
|
||||
bool FeedbackVectorSpec::HasTypeProfileSlot() const {
|
||||
FeedbackSlot slot =
|
||||
FeedbackVector::ToSlot(FeedbackVectorSpec::kTypeProfileSlotIndex);
|
||||
if (slot_count() <= slot.ToInt()) return false;
|
||||
return GetKind(slot) == FeedbackSlotKind::kTypeProfile;
|
||||
}
|
||||
|
||||
static bool IsPropertyNameFeedback(MaybeObject feedback) {
|
||||
HeapObject heap_object;
|
||||
if (!feedback->GetHeapObjectIfStrong(&heap_object)) return false;
|
||||
@ -184,8 +170,6 @@ const char* FeedbackMetadata::Kind2String(FeedbackSlotKind kind) {
|
||||
return "DefineKeyedOwnPropertyInLiteral";
|
||||
case FeedbackSlotKind::kLiteral:
|
||||
return "Literal";
|
||||
case FeedbackSlotKind::kTypeProfile:
|
||||
return "TypeProfile";
|
||||
case FeedbackSlotKind::kForIn:
|
||||
return "ForIn";
|
||||
case FeedbackSlotKind::kInstanceOf:
|
||||
@ -197,13 +181,6 @@ const char* FeedbackMetadata::Kind2String(FeedbackSlotKind kind) {
|
||||
}
|
||||
}
|
||||
|
||||
bool FeedbackMetadata::HasTypeProfileSlot() const {
|
||||
FeedbackSlot slot =
|
||||
FeedbackVector::ToSlot(FeedbackVectorSpec::kTypeProfileSlotIndex);
|
||||
return slot.ToInt() < slot_count() &&
|
||||
GetKind(slot) == FeedbackSlotKind::kTypeProfile;
|
||||
}
|
||||
|
||||
FeedbackSlotKind FeedbackVector::GetKind(FeedbackSlot slot) const {
|
||||
DCHECK(!is_empty());
|
||||
return metadata().GetKind(slot);
|
||||
@ -215,14 +192,6 @@ FeedbackSlotKind FeedbackVector::GetKind(FeedbackSlot slot,
|
||||
return metadata(tag).GetKind(slot);
|
||||
}
|
||||
|
||||
FeedbackSlot FeedbackVector::GetTypeProfileSlot() const {
|
||||
DCHECK(metadata().HasTypeProfileSlot());
|
||||
FeedbackSlot slot =
|
||||
FeedbackVector::ToSlot(FeedbackVectorSpec::kTypeProfileSlotIndex);
|
||||
DCHECK_EQ(FeedbackSlotKind::kTypeProfile, GetKind(slot));
|
||||
return slot;
|
||||
}
|
||||
|
||||
// static
|
||||
Handle<ClosureFeedbackCellArray> ClosureFeedbackCellArray::New(
|
||||
Isolate* isolate, Handle<SharedFunctionInfo> shared) {
|
||||
@ -310,7 +279,6 @@ Handle<FeedbackVector> FeedbackVector::New(
|
||||
case FeedbackSlotKind::kSetKeyedStrict:
|
||||
case FeedbackSlotKind::kStoreInArrayLiteral:
|
||||
case FeedbackSlotKind::kDefineKeyedOwnPropertyInLiteral:
|
||||
case FeedbackSlotKind::kTypeProfile:
|
||||
case FeedbackSlotKind::kInstanceOf:
|
||||
vector->Set(slot, *uninitialized_sentinel, SKIP_WRITE_BARRIER);
|
||||
break;
|
||||
@ -325,8 +293,7 @@ Handle<FeedbackVector> FeedbackVector::New(
|
||||
}
|
||||
|
||||
Handle<FeedbackVector> result = Handle<FeedbackVector>::cast(vector);
|
||||
if (!isolate->is_best_effort_code_coverage() ||
|
||||
isolate->is_collecting_type_profile()) {
|
||||
if (!isolate->is_best_effort_code_coverage()) {
|
||||
AddToVectorsForProfilingTools(isolate, result);
|
||||
}
|
||||
return result;
|
||||
@ -372,8 +339,7 @@ Handle<FeedbackVector> FeedbackVector::NewWithOneCompareSlotForTesting(
|
||||
// static
|
||||
void FeedbackVector::AddToVectorsForProfilingTools(
|
||||
Isolate* isolate, Handle<FeedbackVector> vector) {
|
||||
DCHECK(!isolate->is_best_effort_code_coverage() ||
|
||||
isolate->is_collecting_type_profile());
|
||||
DCHECK(!isolate->is_best_effort_code_coverage());
|
||||
if (!vector->shared_function_info().IsSubjectToDebugging()) return;
|
||||
Handle<ArrayList> list = Handle<ArrayList>::cast(
|
||||
isolate->factory()->feedback_vectors_for_profiling_tools());
|
||||
@ -613,16 +579,6 @@ bool FeedbackNexus::Clear(ClearBehavior behavior) {
|
||||
bool feedback_updated = false;
|
||||
|
||||
switch (kind()) {
|
||||
case FeedbackSlotKind::kTypeProfile:
|
||||
if (V8_LIKELY(behavior == ClearBehavior::kDefault)) {
|
||||
// We don't clear these kinds ever.
|
||||
} else if (!IsCleared()) {
|
||||
DCHECK_EQ(behavior, ClearBehavior::kClearAll);
|
||||
SetFeedback(UninitializedSentinel(), SKIP_WRITE_BARRIER);
|
||||
feedback_updated = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case FeedbackSlotKind::kCompareOp:
|
||||
case FeedbackSlotKind::kForIn:
|
||||
case FeedbackSlotKind::kBinaryOp:
|
||||
@ -849,12 +805,6 @@ InlineCacheState FeedbackNexus::ic_state() const {
|
||||
|
||||
return InlineCacheState::MEGAMORPHIC;
|
||||
}
|
||||
case FeedbackSlotKind::kTypeProfile: {
|
||||
if (feedback == UninitializedSentinel()) {
|
||||
return InlineCacheState::UNINITIALIZED;
|
||||
}
|
||||
return InlineCacheState::MONOMORPHIC;
|
||||
}
|
||||
|
||||
case FeedbackSlotKind::kCloneObject: {
|
||||
if (feedback == UninitializedSentinel()) {
|
||||
@ -1355,120 +1305,6 @@ MaybeHandle<JSObject> FeedbackNexus::GetConstructorFeedback() const {
|
||||
return MaybeHandle<JSObject>();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool InList(Handle<ArrayList> types, Handle<String> type) {
|
||||
for (int i = 0; i < types->Length(); i++) {
|
||||
Object obj = types->Get(i);
|
||||
if (String::cast(obj).Equals(*type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
void FeedbackNexus::Collect(Handle<String> type, int position) {
|
||||
DCHECK(IsTypeProfileKind(kind()));
|
||||
DCHECK_GE(position, 0);
|
||||
DCHECK(config()->can_write());
|
||||
Isolate* isolate = GetIsolate();
|
||||
|
||||
MaybeObject const feedback = GetFeedback();
|
||||
|
||||
// Map source position to collection of types
|
||||
Handle<SimpleNumberDictionary> types;
|
||||
|
||||
if (feedback == UninitializedSentinel()) {
|
||||
types = SimpleNumberDictionary::New(isolate, 1);
|
||||
} else {
|
||||
types = handle(
|
||||
SimpleNumberDictionary::cast(feedback->GetHeapObjectAssumeStrong()),
|
||||
isolate);
|
||||
}
|
||||
|
||||
Handle<ArrayList> position_specific_types;
|
||||
|
||||
InternalIndex entry = types->FindEntry(isolate, position);
|
||||
if (entry.is_not_found()) {
|
||||
position_specific_types = ArrayList::New(isolate, 1);
|
||||
types = SimpleNumberDictionary::Set(
|
||||
isolate, types, position,
|
||||
ArrayList::Add(isolate, position_specific_types, type));
|
||||
} else {
|
||||
DCHECK(types->ValueAt(entry).IsArrayList());
|
||||
position_specific_types =
|
||||
handle(ArrayList::cast(types->ValueAt(entry)), isolate);
|
||||
if (!InList(position_specific_types, type)) { // Add type
|
||||
types = SimpleNumberDictionary::Set(
|
||||
isolate, types, position,
|
||||
ArrayList::Add(isolate, position_specific_types, type));
|
||||
}
|
||||
}
|
||||
SetFeedback(*types);
|
||||
}
|
||||
|
||||
std::vector<int> FeedbackNexus::GetSourcePositions() const {
|
||||
DCHECK(IsTypeProfileKind(kind()));
|
||||
std::vector<int> source_positions;
|
||||
Isolate* isolate = GetIsolate();
|
||||
|
||||
MaybeObject const feedback = GetFeedback();
|
||||
|
||||
if (feedback == UninitializedSentinel()) {
|
||||
return source_positions;
|
||||
}
|
||||
|
||||
Handle<SimpleNumberDictionary> types(
|
||||
SimpleNumberDictionary::cast(feedback->GetHeapObjectAssumeStrong()),
|
||||
isolate);
|
||||
|
||||
for (int index = SimpleNumberDictionary::kElementsStartIndex;
|
||||
index < types->length(); index += SimpleNumberDictionary::kEntrySize) {
|
||||
int key_index = index + SimpleNumberDictionary::kEntryKeyIndex;
|
||||
Object key = types->get(key_index);
|
||||
if (key.IsSmi()) {
|
||||
int position = Smi::cast(key).value();
|
||||
source_positions.push_back(position);
|
||||
}
|
||||
}
|
||||
return source_positions;
|
||||
}
|
||||
|
||||
std::vector<Handle<String>> FeedbackNexus::GetTypesForSourcePositions(
|
||||
uint32_t position) const {
|
||||
DCHECK(IsTypeProfileKind(kind()));
|
||||
Isolate* isolate = GetIsolate();
|
||||
|
||||
MaybeObject const feedback = GetFeedback();
|
||||
std::vector<Handle<String>> types_for_position;
|
||||
if (feedback == UninitializedSentinel()) {
|
||||
return types_for_position;
|
||||
}
|
||||
|
||||
Handle<SimpleNumberDictionary> types(
|
||||
SimpleNumberDictionary::cast(feedback->GetHeapObjectAssumeStrong()),
|
||||
isolate);
|
||||
|
||||
InternalIndex entry = types->FindEntry(isolate, position);
|
||||
if (entry.is_not_found()) return types_for_position;
|
||||
|
||||
DCHECK(types->ValueAt(entry).IsArrayList());
|
||||
Handle<ArrayList> position_specific_types =
|
||||
Handle<ArrayList>(ArrayList::cast(types->ValueAt(entry)), isolate);
|
||||
for (int i = 0; i < position_specific_types->Length(); i++) {
|
||||
Object t = position_specific_types->Get(i);
|
||||
types_for_position.push_back(Handle<String>(String::cast(t), isolate));
|
||||
}
|
||||
|
||||
return types_for_position;
|
||||
}
|
||||
|
||||
void FeedbackNexus::ResetTypeProfile() {
|
||||
DCHECK(IsTypeProfileKind(kind()));
|
||||
SetFeedback(UninitializedSentinel());
|
||||
}
|
||||
|
||||
FeedbackIterator::FeedbackIterator(const FeedbackNexus* nexus)
|
||||
: done_(false), index_(-1), state_(kOther) {
|
||||
DCHECK(
|
||||
|
@ -62,7 +62,6 @@ enum class FeedbackSlotKind : uint8_t {
|
||||
kBinaryOp,
|
||||
kCompareOp,
|
||||
kDefineKeyedOwnPropertyInLiteral,
|
||||
kTypeProfile,
|
||||
kLiteral,
|
||||
kForIn,
|
||||
kInstanceOf,
|
||||
@ -134,10 +133,6 @@ inline bool IsGlobalICKind(FeedbackSlotKind kind) {
|
||||
return IsLoadGlobalICKind(kind) || IsStoreGlobalICKind(kind);
|
||||
}
|
||||
|
||||
inline bool IsTypeProfileKind(FeedbackSlotKind kind) {
|
||||
return kind == FeedbackSlotKind::kTypeProfile;
|
||||
}
|
||||
|
||||
inline bool IsCloneObjectKind(FeedbackSlotKind kind) {
|
||||
return kind == FeedbackSlotKind::kCloneObject;
|
||||
}
|
||||
@ -321,8 +316,6 @@ class FeedbackVector
|
||||
V8_EXPORT_PRIVATE FeedbackSlotKind GetKind(FeedbackSlot slot,
|
||||
AcquireLoadTag tag) const;
|
||||
|
||||
FeedbackSlot GetTypeProfileSlot() const;
|
||||
|
||||
V8_EXPORT_PRIVATE static Handle<FeedbackVector> New(
|
||||
Isolate* isolate, Handle<SharedFunctionInfo> shared,
|
||||
Handle<ClosureFeedbackCellArray> closure_feedback_cell_array,
|
||||
@ -345,7 +338,6 @@ class FeedbackVector
|
||||
DEFINE_SLOT_KIND_PREDICATE(IsDefineNamedOwnIC)
|
||||
DEFINE_SLOT_KIND_PREDICATE(IsStoreGlobalIC)
|
||||
DEFINE_SLOT_KIND_PREDICATE(IsKeyedStoreIC)
|
||||
DEFINE_SLOT_KIND_PREDICATE(IsTypeProfile)
|
||||
#undef DEFINE_SLOT_KIND_PREDICATE
|
||||
|
||||
// Returns typeof mode encoded into kind of given slot.
|
||||
@ -436,13 +428,6 @@ class V8_EXPORT_PRIVATE FeedbackVectorSpec {
|
||||
return slot_kinds_.at(slot.ToInt());
|
||||
}
|
||||
|
||||
bool HasTypeProfileSlot() const;
|
||||
|
||||
// If used, the TypeProfileSlot is always added as the first slot and its
|
||||
// index is constant. If other slots are added before the TypeProfileSlot,
|
||||
// this number changes.
|
||||
static const int kTypeProfileSlotIndex = 0;
|
||||
|
||||
FeedbackSlot AddCallICSlot() { return AddSlot(FeedbackSlotKind::kCall); }
|
||||
|
||||
FeedbackSlot AddLoadICSlot() {
|
||||
@ -524,8 +509,6 @@ class V8_EXPORT_PRIVATE FeedbackVectorSpec {
|
||||
return AddSlot(FeedbackSlotKind::kDefineKeyedOwnPropertyInLiteral);
|
||||
}
|
||||
|
||||
FeedbackSlot AddTypeProfileSlot();
|
||||
|
||||
FeedbackSlot AddCloneObjectSlot() {
|
||||
return AddSlot(FeedbackSlotKind::kCloneObject);
|
||||
}
|
||||
@ -611,7 +594,6 @@ class FeedbackMetadata : public HeapObject {
|
||||
DECL_VERIFIER(FeedbackMetadata)
|
||||
|
||||
static const char* Kind2String(FeedbackSlotKind kind);
|
||||
bool HasTypeProfileSlot() const;
|
||||
|
||||
// Garbage collection support.
|
||||
// This includes any necessary padding at the end of the object for pointer
|
||||
@ -902,16 +884,6 @@ class V8_EXPORT_PRIVATE FeedbackNexus final {
|
||||
// Make sure we don't overflow the smi.
|
||||
static_assert(LEXICAL_MODE_BIT_FIELDS_Ranges::kBitsCount <= kSmiValueSize);
|
||||
|
||||
// For TypeProfile feedback vector slots.
|
||||
// ResetTypeProfile will always reset type profile information.
|
||||
void ResetTypeProfile();
|
||||
|
||||
// Add a type to the list of types for source position <position>.
|
||||
void Collect(Handle<String> type, int position);
|
||||
|
||||
std::vector<int> GetSourcePositions() const;
|
||||
std::vector<Handle<String>> GetTypesForSourcePositions(uint32_t pos) const;
|
||||
|
||||
private:
|
||||
template <typename FeedbackType>
|
||||
inline void SetFeedback(FeedbackType feedback,
|
||||
|
@ -628,7 +628,6 @@ void JSFunction::InitializeFeedbackCell(
|
||||
// profile and more precise code coverage.
|
||||
v8_flags.log_function_events ||
|
||||
!isolate->is_best_effort_code_coverage() ||
|
||||
isolate->is_collecting_type_profile() ||
|
||||
function->shared().sparkplug_compiled();
|
||||
|
||||
if (needs_feedback_vector) {
|
||||
|
@ -28,7 +28,6 @@ UnoptimizedCompileFlags::UnoptimizedCompileFlags(Isolate* isolate,
|
||||
function_kind_(FunctionKind::kNormalFunction),
|
||||
function_syntax_kind_(FunctionSyntaxKind::kDeclaration),
|
||||
parsing_while_debugging_(ParsingWhileDebugging::kNo) {
|
||||
set_collect_type_profile(isolate->is_collecting_type_profile());
|
||||
set_coverage_enabled(!isolate->is_best_effort_code_coverage());
|
||||
set_block_coverage_enabled(isolate->is_block_code_coverage());
|
||||
set_might_always_turbofan(v8_flags.always_turbofan ||
|
||||
@ -60,15 +59,6 @@ UnoptimizedCompileFlags UnoptimizedCompileFlags::ForFunctionCompile(
|
||||
#endif // V8_ENABLE_WEBASSEMBLY
|
||||
flags.set_is_repl_mode(shared.is_repl_mode());
|
||||
|
||||
// CollectTypeProfile uses its own feedback slots. If we have existing
|
||||
// FeedbackMetadata, we can only collect type profile if the feedback vector
|
||||
// has the appropriate slots.
|
||||
flags.set_collect_type_profile(
|
||||
isolate->is_collecting_type_profile() &&
|
||||
(shared.HasFeedbackMetadata()
|
||||
? shared.feedback_metadata().HasTypeProfileSlot()
|
||||
: script.IsUserJavaScript()));
|
||||
|
||||
// Do not support re-parsing top-level function of a wrapped script.
|
||||
DCHECK_IMPLIES(flags.is_toplevel(), !script.is_wrapped());
|
||||
|
||||
@ -82,8 +72,8 @@ UnoptimizedCompileFlags UnoptimizedCompileFlags::ForScriptCompile(
|
||||
|
||||
flags.SetFlagsForFunctionFromScript(script);
|
||||
flags.SetFlagsForToplevelCompile(
|
||||
isolate->is_collecting_type_profile(), script.IsUserJavaScript(),
|
||||
flags.outer_language_mode(), construct_repl_mode(script.is_repl_mode()),
|
||||
script.IsUserJavaScript(), flags.outer_language_mode(),
|
||||
construct_repl_mode(script.is_repl_mode()),
|
||||
script.origin_options().IsModule() ? ScriptType::kModule
|
||||
: ScriptType::kClassic,
|
||||
v8_flags.lazy);
|
||||
@ -99,8 +89,7 @@ UnoptimizedCompileFlags UnoptimizedCompileFlags::ForToplevelCompile(
|
||||
Isolate* isolate, bool is_user_javascript, LanguageMode language_mode,
|
||||
REPLMode repl_mode, ScriptType type, bool lazy) {
|
||||
UnoptimizedCompileFlags flags(isolate, isolate->GetNextScriptId());
|
||||
flags.SetFlagsForToplevelCompile(isolate->is_collecting_type_profile(),
|
||||
is_user_javascript, language_mode, repl_mode,
|
||||
flags.SetFlagsForToplevelCompile(is_user_javascript, language_mode, repl_mode,
|
||||
type, lazy);
|
||||
|
||||
LOG(isolate, ScriptEvent(V8FileLogger::ScriptEventType::kReserveId,
|
||||
@ -143,13 +132,11 @@ void UnoptimizedCompileFlags::SetFlagsFromFunction(T function) {
|
||||
}
|
||||
|
||||
void UnoptimizedCompileFlags::SetFlagsForToplevelCompile(
|
||||
bool is_collecting_type_profile, bool is_user_javascript,
|
||||
LanguageMode language_mode, REPLMode repl_mode, ScriptType type,
|
||||
bool lazy) {
|
||||
bool is_user_javascript, LanguageMode language_mode, REPLMode repl_mode,
|
||||
ScriptType type, bool lazy) {
|
||||
set_is_toplevel(true);
|
||||
set_allow_lazy_parsing(lazy);
|
||||
set_allow_lazy_compile(lazy);
|
||||
set_collect_type_profile(is_user_javascript && is_collecting_type_profile);
|
||||
set_outer_language_mode(
|
||||
stricter_language_mode(outer_language_mode(), language_mode));
|
||||
set_is_repl_mode((repl_mode == REPLMode::kYes));
|
||||
@ -278,8 +265,7 @@ Handle<Script> ParseInfo::CreateScript(
|
||||
} else if (flags().is_eval()) {
|
||||
raw_script.set_compilation_type(Script::COMPILATION_TYPE_EVAL);
|
||||
}
|
||||
CheckFlagsForToplevelCompileFromScript(raw_script,
|
||||
isolate->is_collecting_type_profile());
|
||||
CheckFlagsForToplevelCompileFromScript(raw_script);
|
||||
|
||||
return script;
|
||||
}
|
||||
@ -309,12 +295,9 @@ void ParseInfo::set_character_stream(
|
||||
character_stream_.swap(character_stream);
|
||||
}
|
||||
|
||||
void ParseInfo::CheckFlagsForToplevelCompileFromScript(
|
||||
Script script, bool is_collecting_type_profile) {
|
||||
void ParseInfo::CheckFlagsForToplevelCompileFromScript(Script script) {
|
||||
CheckFlagsForFunctionFromScript(script);
|
||||
DCHECK(flags().is_toplevel());
|
||||
DCHECK_EQ(flags().collect_type_profile(),
|
||||
is_collecting_type_profile && script.IsUserJavaScript());
|
||||
DCHECK_EQ(flags().is_repl_mode(), script.is_repl_mode());
|
||||
|
||||
if (script.is_wrapped()) {
|
||||
|
@ -48,7 +48,6 @@ class Zone;
|
||||
V(is_module, bool, 1, _) \
|
||||
V(allow_lazy_parsing, bool, 1, _) \
|
||||
V(is_lazy_compile, bool, 1, _) \
|
||||
V(collect_type_profile, bool, 1, _) \
|
||||
V(coverage_enabled, bool, 1, _) \
|
||||
V(block_coverage_enabled, bool, 1, _) \
|
||||
V(is_asm_wasm_broken, bool, 1, _) \
|
||||
@ -140,8 +139,7 @@ class V8_EXPORT_PRIVATE UnoptimizedCompileFlags {
|
||||
// SharedFunctionInfo |function|
|
||||
template <typename T>
|
||||
void SetFlagsFromFunction(T function);
|
||||
void SetFlagsForToplevelCompile(bool is_collecting_type_profile,
|
||||
bool is_user_javascript,
|
||||
void SetFlagsForToplevelCompile(bool is_user_javascript,
|
||||
LanguageMode language_mode,
|
||||
REPLMode repl_mode, ScriptType type,
|
||||
bool lazy);
|
||||
@ -345,8 +343,7 @@ class V8_EXPORT_PRIVATE ParseInfo {
|
||||
ReusableUnoptimizedCompileState* reusable_state,
|
||||
uintptr_t stack_limit, RuntimeCallStats* runtime_call_stats);
|
||||
|
||||
void CheckFlagsForToplevelCompileFromScript(Script script,
|
||||
bool is_collecting_type_profile);
|
||||
void CheckFlagsForToplevelCompileFromScript(Script script);
|
||||
|
||||
//------------- Inputs to parsing and scope analysis -----------------------
|
||||
const UnoptimizedCompileFlags flags_;
|
||||
|
@ -1175,35 +1175,6 @@ RUNTIME_FUNCTION(Runtime_DefineKeyedOwnPropertyInLiteral) {
|
||||
return *value;
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_CollectTypeProfile) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(3, args.length());
|
||||
int position = args.smi_value_at(0);
|
||||
Handle<Object> value = args.at(1);
|
||||
Handle<HeapObject> maybe_vector = args.at<HeapObject>(2);
|
||||
|
||||
if (maybe_vector->IsUndefined()) {
|
||||
return ReadOnlyRoots(isolate).undefined_value();
|
||||
}
|
||||
Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
|
||||
|
||||
Handle<String> type = Object::TypeOf(isolate, value);
|
||||
if (value->IsJSReceiver()) {
|
||||
Handle<JSReceiver> object = Handle<JSReceiver>::cast(value);
|
||||
type = JSReceiver::GetConstructorName(isolate, object);
|
||||
} else if (value->IsNull(isolate)) {
|
||||
// typeof(null) is object. But it's more user-friendly to annotate
|
||||
// null as type "null".
|
||||
type = Handle<String>(ReadOnlyRoots(isolate).null_string(), isolate);
|
||||
}
|
||||
|
||||
DCHECK(vector->metadata().HasTypeProfileSlot());
|
||||
FeedbackNexus nexus(vector, vector->GetTypeProfileSlot());
|
||||
nexus.Collect(type, position);
|
||||
|
||||
return ReadOnlyRoots(isolate).undefined_value();
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_HasFastPackedElements) {
|
||||
SealHandleScope shs(isolate);
|
||||
DCHECK_EQ(1, args.length());
|
||||
|
@ -300,7 +300,6 @@ namespace internal {
|
||||
F(AddDictionaryProperty, 3, 1) \
|
||||
F(AddPrivateBrand, 4, 1) \
|
||||
F(AllocateHeapNumber, 0, 1) \
|
||||
F(CollectTypeProfile, 3, 1) \
|
||||
F(CompleteInobjectSlackTrackingForMap, 1, 1) \
|
||||
I(CopyDataProperties, 2, 1) \
|
||||
I(CopyDataPropertiesWithExcludedPropertiesOnStack, -1 /* >= 1 */, 1) \
|
||||
|
@ -60,16 +60,6 @@
|
||||
'runtime/get-properties': [SKIP],
|
||||
}], # not has_webassembly or variant == jitless
|
||||
|
||||
##############################################################################
|
||||
['lite_mode or variant == jitless', {
|
||||
# Lite mode does not allocate feedback vector.
|
||||
'type-profiler/type-profile-start-stop': [SKIP],
|
||||
'type-profiler/type-profile': [SKIP],
|
||||
'type-profiler/type-profile-with-to-string-tag': [SKIP],
|
||||
'type-profiler/type-profile-with-classes': [SKIP],
|
||||
'type-profiler/type-profile-disable': [SKIP],
|
||||
}], # 'lite_mode or variant == jitless'
|
||||
|
||||
##############################################################################
|
||||
['variant == jitless', {
|
||||
# https://crbug.com/v8/7777
|
||||
@ -176,7 +166,6 @@
|
||||
'runtime/context-destroyed-on-context-collected': [SKIP],
|
||||
'runtime/evaluate-async': [SKIP],
|
||||
'runtime/internal-properties-entries': [SKIP],
|
||||
'type-profiler/type-profile-start-stop': [SKIP],
|
||||
}], # gc_stress
|
||||
|
||||
##############################################################################
|
||||
@ -529,11 +518,6 @@
|
||||
'sessions/runtime-evaluate': [SKIP],
|
||||
'sessions/runtime-evaluate-exception': [SKIP],
|
||||
'sessions/runtime-remote-object': [SKIP],
|
||||
'type-profiler/type-profile': [SKIP],
|
||||
'type-profiler/type-profile-disable': [SKIP],
|
||||
'type-profiler/type-profile-start-stop': [SKIP],
|
||||
'type-profiler/type-profile-with-classes': [SKIP],
|
||||
'type-profiler/type-profile-with-to-string-tag': [SKIP],
|
||||
'regress/regress-crbug-1195927': [SKIP],
|
||||
}], # third_party_heap
|
||||
|
||||
|
@ -1,9 +0,0 @@
|
||||
Turn Profiler.startTypeProfile on and off.
|
||||
|
||||
function g(/*Object*/a, /*Array*/b, /*null*/c) {
|
||||
return 'bye';
|
||||
/*string*/};
|
||||
g({}, [], null);
|
||||
|
||||
[
|
||||
]
|
@ -1,45 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
const source =
|
||||
`
|
||||
function g(a, b, c) {
|
||||
return 'bye';
|
||||
};
|
||||
g({}, [], null);
|
||||
`;
|
||||
|
||||
let {session, contextGroup, Protocol} = InspectorTest.start("Turn " +
|
||||
"Profiler.startTypeProfile on and off.");
|
||||
|
||||
(async function testTypeProfile() {
|
||||
Protocol.Runtime.enable();
|
||||
let {result: {scriptId}} = await Protocol.Runtime.compileScript({
|
||||
expression: source,
|
||||
sourceURL: arguments.callee.name, persistScript: true
|
||||
});
|
||||
await Protocol.Profiler.enable();
|
||||
// Start, run, take.
|
||||
await Protocol.Profiler.startTypeProfile();
|
||||
Protocol.Runtime.runScript({scriptId});
|
||||
|
||||
let typeProfiles = await Protocol.Profiler.takeTypeProfile();
|
||||
session.logTypeProfile(typeProfiles.result.result[0],
|
||||
source);
|
||||
|
||||
// This should delete all data.
|
||||
Protocol.Profiler.stopTypeProfile();
|
||||
|
||||
await Protocol.Profiler.startTypeProfile();
|
||||
typeProfiles = await Protocol.Profiler.takeTypeProfile();
|
||||
|
||||
// Should be empty because no code was run since start.
|
||||
InspectorTest.logMessage(typeProfiles.result.result);
|
||||
|
||||
Protocol.Profiler.stopTypeProfile();
|
||||
|
||||
Protocol.Profiler.disable();
|
||||
await Protocol.Runtime.disable();
|
||||
InspectorTest.completeTest();
|
||||
})();
|
@ -1,9 +0,0 @@
|
||||
Test collecting type profile data with Profiler.takeTypeProfile.
|
||||
|
||||
function f(/*Object, number, undefined*/a, /*Array, number, null*/b, /*boolean, Object, symbol*/c) {
|
||||
return 'bye';
|
||||
/*string*/};
|
||||
f({}, [], true);
|
||||
f(3, 2.3, {a: 42});
|
||||
f(undefined, null, Symbol('hello'));
|
||||
/*string*/
|
@ -1,51 +0,0 @@
|
||||
Turn Profiler.startTypeProfile on and off.
|
||||
|
||||
Running test: testTypeProfile
|
||||
|
||||
function g(/*Object*/a, /*Array*/b, /*null*/c) {
|
||||
return 'first';
|
||||
/*string*/};
|
||||
g({}, [], null);
|
||||
|
||||
|
||||
Running test: testTypeProfileFromDifferentSource
|
||||
|
||||
function f(/*null*/a) {
|
||||
return 'second';
|
||||
/*string*/};
|
||||
f(null);
|
||||
|
||||
|
||||
Running test: testStopTypeProfileDeletesFeedback
|
||||
[
|
||||
]
|
||||
|
||||
Running test: testTypeProfileWithoutStartingItFirst
|
||||
Type profile has not been started.
|
||||
|
||||
Running test: testTypeProfileAfterStoppingIt
|
||||
Type profile has not been started.
|
||||
|
||||
Running test: testStartTypeProfileAfterRunning
|
||||
{
|
||||
id : <messageId>
|
||||
result : {
|
||||
result : [
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Running test: testTypeProfileForTwoSources
|
||||
|
||||
function g(/*Object*/a, /*Array*/b, /*null*/c) {
|
||||
return 'first';
|
||||
/*string*/};
|
||||
g({}, [], null);
|
||||
|
||||
|
||||
function f(/*null*/a) {
|
||||
return 'second';
|
||||
/*string*/};
|
||||
f(null);
|
||||
|
||||
Running test: testStopTwice
|
@ -1,176 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
const source1 =
|
||||
`
|
||||
function g(a, b, c) {
|
||||
return 'first';
|
||||
};
|
||||
g({}, [], null);
|
||||
`;
|
||||
|
||||
const source2 =
|
||||
`
|
||||
function f(a) {
|
||||
return 'second';
|
||||
};
|
||||
f(null);
|
||||
`;
|
||||
|
||||
let {session, contextGroup, Protocol} = InspectorTest.start("Turn " +
|
||||
"Profiler.startTypeProfile on and off.");
|
||||
|
||||
InspectorTest.runAsyncTestSuite([
|
||||
async function testTypeProfile() {
|
||||
Protocol.Runtime.enable();
|
||||
let {result: {scriptId}} = await Protocol.Runtime.compileScript({
|
||||
expression: source1,
|
||||
sourceURL: arguments.callee.name, persistScript: true
|
||||
});
|
||||
await Protocol.Profiler.enable();
|
||||
|
||||
// Start, run, take.
|
||||
await Protocol.Profiler.startTypeProfile();
|
||||
Protocol.Runtime.runScript({scriptId});
|
||||
|
||||
let typeProfiles = await Protocol.Profiler.takeTypeProfile();
|
||||
await session.logTypeProfile(typeProfiles.result.result[0],
|
||||
source1);
|
||||
|
||||
Protocol.Profiler.stopTypeProfile();
|
||||
Protocol.Profiler.disable();
|
||||
await Protocol.Runtime.disable();
|
||||
},
|
||||
async function testTypeProfileFromDifferentSource() {
|
||||
Protocol.Runtime.enable();
|
||||
let {result: {scriptId}} = await Protocol.Runtime.compileScript({
|
||||
expression: source2,
|
||||
sourceURL: arguments.callee.name, persistScript: true
|
||||
});
|
||||
await Protocol.Profiler.enable();
|
||||
|
||||
// Start, run different script, take.
|
||||
await Protocol.Profiler.startTypeProfile();
|
||||
Protocol.Runtime.runScript({scriptId});
|
||||
|
||||
let typeProfiles = await Protocol.Profiler.takeTypeProfile();
|
||||
await session.logTypeProfile(typeProfiles.result.result[0],
|
||||
source2);
|
||||
|
||||
Protocol.Profiler.stopTypeProfile();
|
||||
Protocol.Profiler.disable();
|
||||
await Protocol.Runtime.disable();
|
||||
},
|
||||
async function testStopTypeProfileDeletesFeedback() {
|
||||
Protocol.Runtime.enable();
|
||||
let {result: {scriptId}} = await Protocol.Runtime.compileScript({
|
||||
expression: source1,
|
||||
sourceURL: arguments.callee.name, persistScript: true
|
||||
});
|
||||
await Protocol.Profiler.enable();
|
||||
|
||||
// Start, run, stop.
|
||||
await Protocol.Profiler.startTypeProfile();
|
||||
Protocol.Runtime.runScript({scriptId});
|
||||
await Protocol.Profiler.stopTypeProfile();
|
||||
|
||||
// Start, take. Should be empty, because no code was run.
|
||||
await Protocol.Profiler.startTypeProfile();
|
||||
let typeProfiles = await Protocol.Profiler.takeTypeProfile();
|
||||
InspectorTest.logMessage(typeProfiles.result.result);
|
||||
await Protocol.Profiler.stopTypeProfile();
|
||||
|
||||
Protocol.Profiler.disable();
|
||||
await Protocol.Runtime.disable();
|
||||
},
|
||||
async function testTypeProfileWithoutStartingItFirst() {
|
||||
Protocol.Runtime.enable();
|
||||
let {result: {scriptId}} = await Protocol.Runtime.compileScript({ expression: source1,
|
||||
sourceURL: arguments.callee.name, persistScript: true });
|
||||
Protocol.Runtime.runScript({ scriptId });
|
||||
await Protocol.Profiler.enable();
|
||||
|
||||
// This should return an error because type profile was never started.
|
||||
let typeProfiles = await Protocol.Profiler.takeTypeProfile();
|
||||
InspectorTest.logObject(typeProfiles.error.message);
|
||||
|
||||
Protocol.Profiler.disable();
|
||||
await Protocol.Runtime.disable();
|
||||
},
|
||||
async function testTypeProfileAfterStoppingIt() {
|
||||
Protocol.Runtime.enable();
|
||||
let {result: {scriptId}} = await Protocol.Runtime.compileScript({ expression: source1,
|
||||
sourceURL: arguments.callee.name, persistScript: true });
|
||||
Protocol.Runtime.runScript({ scriptId });
|
||||
await Protocol.Profiler.enable();
|
||||
await Protocol.Profiler.startTypeProfile();
|
||||
|
||||
// Make sure that this turns off type profile.
|
||||
await Protocol.Profiler.stopTypeProfile();
|
||||
|
||||
// This should return an error because type profile was stopped.
|
||||
let typeProfiles = await Protocol.Profiler.takeTypeProfile();
|
||||
InspectorTest.logObject(typeProfiles.error.message);
|
||||
|
||||
Protocol.Profiler.disable();
|
||||
await Protocol.Runtime.disable();
|
||||
},
|
||||
async function testStartTypeProfileAfterRunning() {
|
||||
Protocol.Runtime.enable();
|
||||
let {result: {scriptId}} = await Protocol.Runtime.compileScript({
|
||||
expression: source1,
|
||||
sourceURL: arguments.callee.name, persistScript: true
|
||||
});
|
||||
Protocol.Runtime.runScript({scriptId});
|
||||
|
||||
await Protocol.Profiler.enable();
|
||||
await Protocol.Profiler.startTypeProfile();
|
||||
|
||||
let typeProfiles = await Protocol.Profiler.takeTypeProfile();
|
||||
|
||||
// This should be empty because type profile was started after compilation.
|
||||
// Only the outer script is annotated with return value "string" because
|
||||
// that does not depend on runScript().
|
||||
InspectorTest.logMessage(typeProfiles);
|
||||
|
||||
Protocol.Profiler.stopTypeProfile();
|
||||
Protocol.Profiler.disable();
|
||||
await Protocol.Runtime.disable();
|
||||
},
|
||||
async function testTypeProfileForTwoSources() {
|
||||
Protocol.Runtime.enable();
|
||||
let {result: {scriptId: scriptId1}} = await Protocol.Runtime.compileScript({
|
||||
expression: source1,
|
||||
sourceURL: arguments.callee.name, persistScript: true
|
||||
});
|
||||
let {result: {scriptId: scriptId2}} = await Protocol.Runtime.compileScript({
|
||||
expression: source2,
|
||||
sourceURL: arguments.callee.name, persistScript: true
|
||||
});
|
||||
await Protocol.Profiler.enable();
|
||||
|
||||
// Start, run different script, take.
|
||||
await Protocol.Profiler.startTypeProfile();
|
||||
Protocol.Runtime.runScript({scriptId: scriptId1});
|
||||
Protocol.Runtime.runScript({scriptId: scriptId2});
|
||||
|
||||
let typeProfiles = await Protocol.Profiler.takeTypeProfile();
|
||||
await session.logTypeProfile(typeProfiles.result.result[0],
|
||||
source1);
|
||||
await session.logTypeProfile(typeProfiles.result.result[1],
|
||||
source2);
|
||||
|
||||
Protocol.Profiler.stopTypeProfile();
|
||||
Protocol.Profiler.disable();
|
||||
await Protocol.Runtime.disable();
|
||||
},
|
||||
async function testStopTwice() {
|
||||
Protocol.Runtime.enable();
|
||||
await Protocol.Profiler.enable();
|
||||
await Protocol.Profiler.stopTypeProfile();
|
||||
await Protocol.Profiler.stopTypeProfile();
|
||||
Protocol.Profiler.disable();
|
||||
await Protocol.Runtime.disable();
|
||||
},
|
||||
]);
|
@ -1,16 +0,0 @@
|
||||
Test collecting type profile data with Profiler.takeTypeProfile.
|
||||
|
||||
function f(/*number*/n) {
|
||||
/*undefined*/};
|
||||
f(5);
|
||||
function g(/*Object, number*/a, /*Array, number*/b, /*Flower, Object*/c) {
|
||||
return 'bye';
|
||||
/*string*/};
|
||||
/*undefined*/class Tree {};
|
||||
/*Flower*/class Flower extends Tree{};
|
||||
var f = new Flower();
|
||||
f.constructor = {};
|
||||
f.constructor.name = "Not a flower.";
|
||||
g({}, [], f);
|
||||
g(3, 2.3, {a: 42});
|
||||
/*string*/
|
@ -1,41 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
const source =
|
||||
`
|
||||
function f(n) {
|
||||
};
|
||||
f(5);
|
||||
function g(a, b, c) {
|
||||
return 'bye';
|
||||
};
|
||||
class Tree {};
|
||||
class Flower extends Tree{};
|
||||
var f = new Flower();
|
||||
f.constructor = {};
|
||||
f.constructor.name = "Not a flower.";
|
||||
g({}, [], f);
|
||||
g(3, 2.3, {a: 42});
|
||||
`;
|
||||
|
||||
let {session, contextGroup, Protocol} = InspectorTest.start("Test collecting type profile data with Profiler.takeTypeProfile.");
|
||||
|
||||
(async function testTypeProfile(next) {
|
||||
await Protocol.Profiler.enable();
|
||||
await Protocol.Profiler.startTypeProfile();
|
||||
|
||||
Protocol.Runtime.enable();
|
||||
let {result: {scriptId}} = await Protocol.Runtime.compileScript({ expression: source,
|
||||
sourceURL: arguments.callee.name, persistScript: true });
|
||||
|
||||
Protocol.Runtime.runScript({ scriptId });
|
||||
|
||||
let typeProfiles = await Protocol.Profiler.takeTypeProfile();
|
||||
await session.logTypeProfile(typeProfiles.result.result[0],
|
||||
source);
|
||||
|
||||
Protocol.Profiler.disable();
|
||||
await Protocol.Runtime.disable();
|
||||
InspectorTest.completeTest();
|
||||
})();
|
@ -1,17 +0,0 @@
|
||||
Test collecting type profile data with Profiler.takeTypeProfile.
|
||||
|
||||
function g(/*Object, number*/a, /*Array, number*/b, /*Dog, Object*/c) {
|
||||
return 'bye';
|
||||
/*string*/};
|
||||
/*undefined*/class Tree {};
|
||||
/*Flower*/class Flower extends Tree{};
|
||||
var f = new Flower();
|
||||
// We store the type when a variable is used. If a toStringTag is
|
||||
// changes the type, we want to collect that changed feedback.
|
||||
// This tests ensures that we collect that information rather than
|
||||
// for example infer the types from the internal map, which wouldn't
|
||||
// know about a toStringTag.
|
||||
f[Symbol.toStringTag] = 'Dog';
|
||||
g({}, [], f);
|
||||
g(3, 2.3, {a: 42});
|
||||
/*string*/
|
@ -1,44 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
const source =
|
||||
`
|
||||
function g(a, b, c) {
|
||||
return 'bye';
|
||||
};
|
||||
class Tree {};
|
||||
class Flower extends Tree{};
|
||||
var f = new Flower();
|
||||
// We store the type when a variable is used. If a toStringTag is
|
||||
// changes the type, we want to collect that changed feedback.
|
||||
// This tests ensures that we collect that information rather than
|
||||
// for example infer the types from the internal map, which wouldn't
|
||||
// know about a toStringTag.
|
||||
f[Symbol.toStringTag] = 'Dog';
|
||||
g({}, [], f);
|
||||
g(3, 2.3, {a: 42});
|
||||
`;
|
||||
|
||||
let {session, contextGroup, Protocol} = InspectorTest.start("Test collecting " +
|
||||
"type profile data with Profiler.takeTypeProfile.");
|
||||
|
||||
(async function testTypeProfile() {
|
||||
await Protocol.Profiler.enable();
|
||||
await Protocol.Profiler.startTypeProfile();
|
||||
|
||||
Protocol.Runtime.enable();
|
||||
let {result: {scriptId}} = await Protocol.Runtime.compileScript({ expression: source,
|
||||
sourceURL: arguments.callee.name, persistScript: true });
|
||||
Protocol.Runtime.runScript({ scriptId });
|
||||
await Protocol.Profiler.startTypeProfile();
|
||||
|
||||
let typeProfiles = await Protocol.Profiler.takeTypeProfile();
|
||||
await session.logTypeProfile(typeProfiles.result.result[0],
|
||||
source);
|
||||
|
||||
Protocol.Profiler.stopTypeProfile();
|
||||
Protocol.Profiler.disable();
|
||||
await Protocol.Runtime.disable();
|
||||
InspectorTest.completeTest();
|
||||
})();
|
@ -1,37 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
const source =
|
||||
`
|
||||
function f(a, b, c) {
|
||||
return 'bye';
|
||||
};
|
||||
f({}, [], true);
|
||||
f(3, 2.3, {a: 42});
|
||||
f(undefined, null, Symbol('hello'));
|
||||
`;
|
||||
|
||||
let {session, contextGroup, Protocol} = InspectorTest.start("Test collecting type profile data with Profiler.takeTypeProfile.");
|
||||
|
||||
(async function testTypeProfile() {
|
||||
await Protocol.Profiler.enable();
|
||||
await Protocol.Profiler.startTypeProfile();
|
||||
|
||||
Protocol.Runtime.enable();
|
||||
let {result: {scriptId}} = await Protocol.Runtime.compileScript({
|
||||
expression: source,
|
||||
sourceURL: arguments.callee.name,
|
||||
persistScript: true
|
||||
});
|
||||
Protocol.Runtime.runScript({ scriptId });
|
||||
|
||||
let typeProfiles = await Protocol.Profiler.takeTypeProfile();
|
||||
await session.logTypeProfile(typeProfiles.result.result[0],
|
||||
source);
|
||||
|
||||
Protocol.Profiler.stopTypeProfile();
|
||||
Protocol.Profiler.disable();
|
||||
await Protocol.Runtime.disable();
|
||||
InspectorTest.completeTest();
|
||||
})();
|
@ -1,11 +0,0 @@
|
||||
// Copyright 2020 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: --allow-natives-syntax
|
||||
|
||||
function f(a, b, c) {
|
||||
return 'bye';
|
||||
};
|
||||
|
||||
%CollectTypeProfile(0, f, undefined);
|
@ -484,10 +484,6 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
|
||||
// Insert entry for illegal bytecode as this is never willingly emitted.
|
||||
scorecard[Bytecodes::ToByte(Bytecode::kIllegal)] = 1;
|
||||
|
||||
// Bytecode for CollectTypeProfile is only emitted when
|
||||
// Type Information for DevTools is turned on.
|
||||
scorecard[Bytecodes::ToByte(Bytecode::kCollectTypeProfile)] = 1;
|
||||
|
||||
// This bytecode is too inconvenient to test manually.
|
||||
scorecard[Bytecodes::ToByte(
|
||||
Bytecode::kFindNonDefaultConstructorOrConstruct)] = 1;
|
||||
|
Loading…
Reference in New Issue
Block a user