[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:
Marja Hölttä 2022-10-07 14:40:05 +02:00 committed by V8 LUCI CQ
parent 4e2ecbd2d7
commit 283791d250
46 changed files with 15 additions and 1263 deletions

View File

@ -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",

View File

@ -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",

View File

@ -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": [

View File

@ -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

View File

@ -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));

View File

@ -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,

View File

@ -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),

View File

@ -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:

View File

@ -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);

View File

@ -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(

View File

@ -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

View File

@ -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_

View File

@ -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)

View File

@ -1333,7 +1333,6 @@ void FeedbackNexus::Print(std::ostream& os) {
break;
}
case FeedbackSlotKind::kLiteral:
case FeedbackSlotKind::kTypeProfile:
break;
case FeedbackSlotKind::kJumpLoop:
os << "JumpLoop";

View File

@ -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

View File

@ -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() {

View File

@ -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(); }

View File

@ -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));

View File

@ -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);

View File

@ -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) {

View File

@ -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.

View File

@ -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();
}

View File

@ -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, \

View File

@ -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

View File

@ -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>();

View File

@ -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;

View File

@ -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(

View File

@ -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,

View File

@ -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) {

View File

@ -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()) {

View File

@ -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_;

View File

@ -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());

View File

@ -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) \

View File

@ -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

View File

@ -1,9 +0,0 @@
Turn Profiler.startTypeProfile on and off.
function g(/*Object*/a, /*Array*/b, /*null*/c) {
return 'bye';
/*string*/};
g({}, [], null);
[
]

View File

@ -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();
})();

View File

@ -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*/

View File

@ -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

View File

@ -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();
},
]);

View File

@ -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*/

View File

@ -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();
})();

View File

@ -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*/

View File

@ -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();
})();

View File

@ -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();
})();

View File

@ -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);

View File

@ -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;