#include <limits>
#include <memory>
#include "include/libplatform/v8-tracing.h"
#include "include/v8-fast-api-calls.h"
#include "include/v8-function.h"
#include "include/v8-json.h"
#include "include/v8-locker.h"
#include "include/v8-profiler.h"
#include "src/api/api-inl.h"
#include "src/base/platform/platform.h"
#include "src/base/strings.h"
#include "src/codegen/compilation-cache.h"
#include "src/codegen/source-position-table.h"
#include "src/deoptimizer/deoptimize-reason.h"
#include "src/execution/embedder-state.h"
#include "src/execution/protectors-inl.h"
#include "src/flags/flags.h"
#include "src/heap/spaces.h"
#include "src/init/v8.h"
#include "src/libsampler/sampler.h"
#include "src/logging/log.h"
#include "src/objects/objects-inl.h"
#include "src/profiler/cpu-profiler.h"
#include "src/profiler/profiler-listener.h"
#include "src/profiler/symbolizer.h"
#include "src/utils/utils.h"
#include "test/cctest/cctest.h"
#include "test/cctest/heap/heap-utils.h"
#include "test/cctest/jsonstream-helper.h"
#include "test/cctest/profiler-extension.h"
#include "test/common/flag-utils.h"
#ifdef V8_USE_PERFETTO
#include "protos/perfetto/trace/trace.pb.h"
#include "src/libplatform/tracing/trace-event-listener.h"
#endif
namespace v8 {
namespace internal {
namespace test_cpu_profiler {
static v8::Local<v8::Function> GetFunction(v8::Local<v8::Context> env,
const char* name) { … }
static size_t offset(const char* src, const char* substring) { … }
template <typename A, typename B>
static int dist(A a, B b) { … }
static const char* reason(const i::DeoptimizeReason reason) { … }
TEST(StartStop) { … }
static void EnqueueTickSampleEvent(ProfilerEventsProcessor* proc,
i::Address frame1,
i::Address frame2 = kNullAddress,
i::Address frame3 = kNullAddress) { … }
namespace {
class TestSetup { … };
}
i::Tagged<i::AbstractCode> CreateCode(i::Isolate* isolate, LocalContext* env) { … }
TEST(CodeEvents) { … }
template <typename T>
static int CompareProfileNodes(const T* p1, const T* p2) { … }
TEST(TickEvents) { … }
TEST(CodeMapClearedBetweenProfilesWithLazyLogging) { … }
TEST(CodeMapNotClearedBetweenProfilesWithEagerLogging) { … }
TEST(CrashIfStoppingLastNonExistentProfile) { … }
TEST(Issue1398) { … }
TEST(DeleteAllCpuProfiles) { … }
static bool FindCpuProfile(v8::CpuProfiler* v8profiler,
const v8::CpuProfile* v8profile) { … }
TEST(DeleteCpuProfile) { … }
TEST(ProfileStartEndTime) { … }
class ProfilerHelper { … };
v8::CpuProfile* ProfilerHelper::Run(v8::Local<v8::Function> function,
v8::Local<v8::Value> argv[], int argc,
unsigned min_js_samples,
unsigned min_external_samples,
ProfilingMode mode, unsigned max_samples,
v8::Local<v8::Context> context) { … }
static unsigned TotalHitCount(const v8::CpuProfileNode* node) { … }
static unsigned TotalHitCount(const v8::CpuProfileNode* node,
const std::string& name) { … }
static const v8::CpuProfileNode* FindChild(v8::Local<v8::Context> context,
const v8::CpuProfileNode* node,
const char* name) { … }
static const v8::CpuProfileNode* FindChild(const v8::CpuProfileNode* node,
const char* name) { … }
static const v8::CpuProfileNode* GetChild(v8::Local<v8::Context> context,
const v8::CpuProfileNode* node,
const char* name) { … }
static void CheckSimpleBranch(v8::Local<v8::Context> context,
const v8::CpuProfileNode* node,
const char* names[], int length) { … }
static const ProfileNode* GetSimpleBranch(v8::Local<v8::Context> context,
v8::CpuProfile* profile,
const char* names[], int length) { … }
struct NameLinePair { … };
static const v8::CpuProfileNode* FindChild(const v8::CpuProfileNode* node,
NameLinePair pair) { … }
static const v8::CpuProfileNode* GetChild(const v8::CpuProfileNode* node,
NameLinePair pair) { … }
static void CheckBranch(const v8::CpuProfileNode* node, NameLinePair path[],
int length) { … }
static const char* cpu_profiler_test_source = …;
TEST(CollectCpuProfile) { … }
TEST(CollectCpuProfileCallerLineNumbers) { … }
static const char* hot_deopt_no_frame_entry_test_source = …;
TEST(HotDeoptNoFrameEntry) { … }
TEST(CollectCpuProfileSamples) { … }
static const char* cpu_profiler_test_source2 = …;
TEST(SampleWhenFrameIsNotSetup) { … }
static const char* native_accessor_test_source = …;
class TestApiCallbacks { … };
TEST(NativeAccessorUninitializedIC) { … }
TEST(NativeAccessorMonomorphicIC) { … }
static const char* native_method_test_source = …;
TEST(NativeMethodUninitializedIC) { … }
TEST(NativeMethodMonomorphicIC) { … }
static const char* bound_function_test_source = …;
TEST(BoundFunctionCall) { … }
static void TickLines(bool optimize) { … }
TEST(TickLinesBaseline) { … }
TEST(TickLinesOptimized) { … }
static const char* call_function_test_source = …;
TEST(FunctionCallSample) { … }
static const char* function_apply_test_source = …;
TEST(FunctionApplySample) { … }
static const char* cpu_profiler_deep_stack_test_source = …;
TEST(CpuProfileDeepStack) { … }
static const char* js_native_js_test_source = …;
static void CallJsFunction(const v8::FunctionCallbackInfo<v8::Value>& info) { … }
TEST(JsNativeJsSample) { … }
static const char* js_native_js_runtime_js_test_source = …;
TEST(JsNativeJsRuntimeJsSample) { … }
static void CallJsFunction2(const v8::FunctionCallbackInfo<v8::Value>& info) { … }
static const char* js_native1_js_native2_js_test_source = …;
TEST(JsNative1JsNative2JsSample) { … }
static const char* js_force_collect_sample_source = …;
static void CallCollectSample(const v8::FunctionCallbackInfo<v8::Value>& info) { … }
void InstallCollectSampleFunction(v8::Local<v8::Context> env) { … }
TEST(CollectSampleAPI) { … }
static const char* js_native_js_runtime_multiple_test_source = …;
TEST(JsNativeJsRuntimeJsSampleMultiple) { … }
static const char* inlining_test_source = …;
TEST(Inlining) { … }
static const char* inlining_test_source2 = …;
TEST(Inlining2) { … }
static const char* cross_script_source_a = …;
static const char* cross_script_source_b = …;
TEST(CrossScriptInliningCallerLineNumbers) { … }
static const char* cross_script_source_c = …;
static const char* cross_script_source_d = …;
static const char* cross_script_source_e = …;
static const char* cross_script_source_f = …;
TEST(CrossScriptInliningCallerLineNumbers2) { … }
TEST(IdleTime) { … }
static void CheckFunctionDetails(v8::Isolate* isolate,
const v8::CpuProfileNode* node,
const char* name, const char* script_name,
bool is_shared_cross_origin, int script_id,
int line, int column,
const v8::CpuProfileNode* parent) { … }
TEST(FunctionDetails) { … }
TEST(FunctionDetailsInlining) { … }
static const char* pre_profiling_osr_script = …;
TEST(StartProfilingAfterOsr) { … }
TEST(DontStopOnFinishedProfileDelete) { … }
const char* GetBranchDeoptReason(v8::Local<v8::Context> context,
i::CpuProfile* iprofile, const char* branch[],
int length) { … }
TEST(CollectDeoptEvents) { … }
TEST(SourceLocation) { … }
static const char* inlined_source = …;
TEST(DeoptAtFirstLevelInlinedSource) { … }
TEST(DeoptAtSecondLevelInlinedSource) { … }
TEST(DeoptUntrackedFunction) { … }
TraceBuffer;
TraceConfig;
TraceObject;
namespace {
#ifdef V8_USE_PERFETTO
class CpuProfilerListener : public platform::tracing::TraceEventListener { … };
#else
class CpuProfileEventChecker : public v8::platform::tracing::TraceWriter {
public:
void AppendTraceEvent(TraceObject* trace_event) override {
if (trace_event->name() != std::string("Profile") &&
trace_event->name() != std::string("ProfileChunk"))
return;
CHECK(!profile_id_ || trace_event->id() == profile_id_);
CHECK_EQ(1, trace_event->num_args());
CHECK_EQ(TRACE_VALUE_TYPE_CONVERTABLE, trace_event->arg_types()[0]);
profile_id_ = trace_event->id();
v8::ConvertableToTraceFormat* arg =
trace_event->arg_convertables()[0].get();
result_json_ += result_json_.empty() ? "[" : ",\n";
arg->AppendAsTraceFormat(&result_json_);
}
void Flush() override { result_json_ += "]"; }
const std::string& result_json() const { return result_json_; }
void Reset() {
result_json_.clear();
profile_id_ = 0;
}
private:
std::string result_json_;
uint64_t profile_id_ = 0;
};
#endif
}
TEST(TracingCpuProfiler) { … }
TEST(Issue763073) { … }
static const char* js_collect_sample_api_source = …;
static void CallStaticCollectSample(
const v8::FunctionCallbackInfo<v8::Value>& info) { … }
TEST(StaticCollectSampleAPI) { … }
TEST(CodeEntriesMemoryLeak) { … }
TEST(NativeFrameStackTrace) { … }
TEST(SourcePositionTable) { … }
TEST(MultipleProfilers) { … }
TEST(CrashReusedProfiler) { … }
TEST(MultipleProfilersSampleIndependently) { … }
void ProfileSomeCode(v8::Isolate* isolate) { … }
class IsolateThread : public v8::base::Thread { … };
TEST(MultipleIsolates) { … }
const char* varying_frame_size_script = …;
class UnlockingThread : public v8::base::Thread { … };
TEST(MultipleThreadsSingleIsolate) { … }
TEST(FastStopProfiling) { … }
TEST(MaxSimultaneousProfiles) { … }
TEST(LowPrecisionSamplingStartStopInternal) { … }
TEST(LowPrecisionSamplingStartStopPublic) { … }
const char* naming_test_source = …;
TEST(StandardNaming) { … }
TEST(DebugNaming) { … }
TEST(SampleLimit) { … }
TEST(ProflilerSubsampling) { … }
TEST(DynamicResampling) { … }
TEST(DynamicResamplingWithBaseInterval) { … }
TEST(Bug9151StaleCodeEntries) { … }
TEST(ContextIsolation) { … }
void ValidateEmbedderState(v8::CpuProfile* profile,
EmbedderStateTag expected_tag) { … }
TEST(EmbedderContextIsolation) { … }
TEST(EmbedderStatePropagate) { … }
TEST(EmbedderStatePropagateNativeContextMove) { … }
TEST(ContextFilterMovedNativeContext) { … }
enum class EntryCountMode { … };
int GetSourcePositionEntryCount(i::Isolate* isolate, const char* source,
EntryCountMode mode = EntryCountMode::kAll) { … }
UNINITIALIZED_TEST(DetailedSourcePositionAPI) { … }
UNINITIALIZED_TEST(DetailedSourcePositionAPI_Inlining) { … }
namespace {
struct FastApiReceiver { … };
}
v8::Local<v8::Function> CreateApiCode(LocalContext* env) { … }
TEST(CanStartStopProfilerWithTitlesAndIds) { … }
TEST(NoProfilingProtectorCPUProfiler) { … }
TEST(FastApiCPUProfiler) { … }
TEST(BytecodeFlushEventsEagerLogging) { … }
TEST(ClearUnusedWithEagerLogging) { … }
TEST(SkipEstimatedSizeWhenActiveProfiling) { … }
TEST(CpuProfileJSONSerialization) { … }
}
}
}