Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(195)

Unified Diff: test/cctest/test-profile-generator.cc

Issue 148503002: A64: Synchronize with r15545. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « test/cctest/test-platform-tls.cc ('k') | test/cctest/test-regexp.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/cctest/test-profile-generator.cc
diff --git a/test/cctest/test-profile-generator.cc b/test/cctest/test-profile-generator.cc
index 17c9dd9f015e76d4e2b9418a2f0a14e992ede21f..7b8278ba660d4d490a026af108308b1c756e3043 100644
--- a/test/cctest/test-profile-generator.cc
+++ b/test/cctest/test-profile-generator.cc
@@ -30,6 +30,7 @@
#include "v8.h"
#include "profile-generator-inl.h"
#include "cctest.h"
+#include "cpu-profiler.h"
#include "../include/v8-profiler.h"
using i::CodeEntry;
@@ -42,62 +43,23 @@ using i::ProfileTree;
using i::ProfileGenerator;
using i::SampleRateCalculator;
using i::TickSample;
-using i::TokenEnumerator;
using i::Vector;
-namespace v8 {
-namespace internal {
-
-class TokenEnumeratorTester {
- public:
- static i::List<bool>* token_removed(TokenEnumerator* te) {
- return &te->token_removed_;
- }
-};
-
-} } // namespace v8::internal
-
-TEST(TokenEnumerator) {
- TokenEnumerator te;
- CHECK_EQ(TokenEnumerator::kNoSecurityToken, te.GetTokenId(NULL));
- v8::HandleScope hs(v8::Isolate::GetCurrent());
- v8::Local<v8::String> token1(v8::String::New("1x"));
- CHECK_EQ(0, te.GetTokenId(*v8::Utils::OpenHandle(*token1)));
- CHECK_EQ(0, te.GetTokenId(*v8::Utils::OpenHandle(*token1)));
- v8::Local<v8::String> token2(v8::String::New("2x"));
- CHECK_EQ(1, te.GetTokenId(*v8::Utils::OpenHandle(*token2)));
- CHECK_EQ(1, te.GetTokenId(*v8::Utils::OpenHandle(*token2)));
- CHECK_EQ(0, te.GetTokenId(*v8::Utils::OpenHandle(*token1)));
- {
- v8::HandleScope hs(v8::Isolate::GetCurrent());
- v8::Local<v8::String> token3(v8::String::New("3x"));
- CHECK_EQ(2, te.GetTokenId(*v8::Utils::OpenHandle(*token3)));
- CHECK_EQ(1, te.GetTokenId(*v8::Utils::OpenHandle(*token2)));
- CHECK_EQ(0, te.GetTokenId(*v8::Utils::OpenHandle(*token1)));
- }
- CHECK(!i::TokenEnumeratorTester::token_removed(&te)->at(2));
- HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
- CHECK(i::TokenEnumeratorTester::token_removed(&te)->at(2));
- CHECK_EQ(1, te.GetTokenId(*v8::Utils::OpenHandle(*token2)));
- CHECK_EQ(0, te.GetTokenId(*v8::Utils::OpenHandle(*token1)));
-}
-
-
TEST(ProfileNodeFindOrAddChild) {
ProfileTree tree;
ProfileNode node(&tree, NULL);
- CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa");
+ CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
ProfileNode* childNode1 = node.FindOrAddChild(&entry1);
CHECK_NE(NULL, childNode1);
CHECK_EQ(childNode1, node.FindOrAddChild(&entry1));
- CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb");
+ CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
ProfileNode* childNode2 = node.FindOrAddChild(&entry2);
CHECK_NE(NULL, childNode2);
CHECK_NE(childNode1, childNode2);
CHECK_EQ(childNode1, node.FindOrAddChild(&entry1));
CHECK_EQ(childNode2, node.FindOrAddChild(&entry2));
- CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc");
+ CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
ProfileNode* childNode3 = node.FindOrAddChild(&entry3);
CHECK_NE(NULL, childNode3);
CHECK_NE(childNode1, childNode3);
@@ -109,20 +71,18 @@ TEST(ProfileNodeFindOrAddChild) {
TEST(ProfileNodeFindOrAddChildForSameFunction) {
- const char* empty = "";
const char* aaa = "aaa";
ProfileTree tree;
ProfileNode node(&tree, NULL);
- CodeEntry entry1(i::Logger::FUNCTION_TAG, empty, aaa);
+ CodeEntry entry1(i::Logger::FUNCTION_TAG, aaa);
ProfileNode* childNode1 = node.FindOrAddChild(&entry1);
CHECK_NE(NULL, childNode1);
CHECK_EQ(childNode1, node.FindOrAddChild(&entry1));
// The same function again.
- CodeEntry entry2(i::Logger::FUNCTION_TAG, empty, aaa);
+ CodeEntry entry2(i::Logger::FUNCTION_TAG, aaa);
CHECK_EQ(childNode1, node.FindOrAddChild(&entry2));
// Now with a different security token.
- CodeEntry entry3(i::Logger::FUNCTION_TAG, empty, aaa,
- TokenEnumerator::kNoSecurityToken + 1);
+ CodeEntry entry3(i::Logger::FUNCTION_TAG, aaa);
CHECK_EQ(childNode1, node.FindOrAddChild(&entry3));
}
@@ -157,9 +117,9 @@ class ProfileTreeTestHelper {
} // namespace
TEST(ProfileTreeAddPathFromStart) {
- CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa");
- CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb");
- CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc");
+ CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
+ CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
+ CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
ProfileTree tree;
ProfileTreeTestHelper helper(&tree);
CHECK_EQ(NULL, helper.Walk(&entry1));
@@ -224,9 +184,9 @@ TEST(ProfileTreeAddPathFromStart) {
TEST(ProfileTreeAddPathFromEnd) {
- CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa");
- CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb");
- CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc");
+ CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
+ CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
+ CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
ProfileTree tree;
ProfileTreeTestHelper helper(&tree);
CHECK_EQ(NULL, helper.Walk(&entry1));
@@ -304,7 +264,7 @@ TEST(ProfileTreeCalculateTotalTicks) {
CHECK_EQ(1, empty_tree.root()->total_ticks());
CHECK_EQ(1, empty_tree.root()->self_ticks());
- CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa");
+ CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
CodeEntry* e1_path[] = {&entry1};
Vector<CodeEntry*> e1_path_vec(
e1_path, sizeof(e1_path) / sizeof(e1_path[0]));
@@ -325,7 +285,7 @@ TEST(ProfileTreeCalculateTotalTicks) {
CHECK_EQ(1, node1->total_ticks());
CHECK_EQ(1, node1->self_ticks());
- CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb");
+ CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
CodeEntry* e1_e2_path[] = {&entry1, &entry2};
Vector<CodeEntry*> e1_e2_path_vec(
e1_e2_path, sizeof(e1_e2_path) / sizeof(e1_e2_path[0]));
@@ -360,7 +320,7 @@ TEST(ProfileTreeCalculateTotalTicks) {
CodeEntry* e2_path[] = {&entry2};
Vector<CodeEntry*> e2_path_vec(
e2_path, sizeof(e2_path) / sizeof(e2_path[0]));
- CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc");
+ CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
CodeEntry* e3_path[] = {&entry3};
Vector<CodeEntry*> e3_path_vec(
e3_path, sizeof(e3_path) / sizeof(e3_path[0]));
@@ -415,114 +375,17 @@ TEST(ProfileTreeCalculateTotalTicks) {
}
-TEST(ProfileTreeFilteredClone) {
- ProfileTree source_tree;
- const int token0 = 0, token1 = 1, token2 = 2;
- CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", token0);
- CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb", token1);
- CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc", token0);
- CodeEntry entry4(i::Logger::FUNCTION_TAG, "", "ddd",
- TokenEnumerator::kInheritsSecurityToken);
-
- {
- CodeEntry* e1_e2_path[] = {&entry1, &entry2};
- Vector<CodeEntry*> e1_e2_path_vec(
- e1_e2_path, sizeof(e1_e2_path) / sizeof(e1_e2_path[0]));
- source_tree.AddPathFromStart(e1_e2_path_vec);
- CodeEntry* e2_e4_path[] = {&entry2, &entry4};
- Vector<CodeEntry*> e2_e4_path_vec(
- e2_e4_path, sizeof(e2_e4_path) / sizeof(e2_e4_path[0]));
- source_tree.AddPathFromStart(e2_e4_path_vec);
- CodeEntry* e3_e1_path[] = {&entry3, &entry1};
- Vector<CodeEntry*> e3_e1_path_vec(
- e3_e1_path, sizeof(e3_e1_path) / sizeof(e3_e1_path[0]));
- source_tree.AddPathFromStart(e3_e1_path_vec);
- CodeEntry* e3_e2_path[] = {&entry3, &entry2};
- Vector<CodeEntry*> e3_e2_path_vec(
- e3_e2_path, sizeof(e3_e2_path) / sizeof(e3_e2_path[0]));
- source_tree.AddPathFromStart(e3_e2_path_vec);
- source_tree.CalculateTotalTicks();
- // Results in -> {entry1,0,1,0} -> {entry2,1,1,1}
- // {root,0,4,-1} -> {entry2,0,1,1} -> {entry4,1,1,inherits}
- // -> {entry3,0,2,0} -> {entry1,1,1,0}
- // -> {entry2,1,1,1}
- CHECK_EQ(4, source_tree.root()->total_ticks());
- CHECK_EQ(0, source_tree.root()->self_ticks());
- }
-
- {
- ProfileTree token0_tree;
- token0_tree.FilteredClone(&source_tree, token0);
- // Should be -> {entry1,1,1,0}
- // {root,1,4,-1} -> {entry3,1,2,0} -> {entry1,1,1,0}
- // [self ticks from filtered nodes are attributed to their parents]
- CHECK_EQ(4, token0_tree.root()->total_ticks());
- CHECK_EQ(1, token0_tree.root()->self_ticks());
- ProfileTreeTestHelper token0_helper(&token0_tree);
- ProfileNode* node1 = token0_helper.Walk(&entry1);
- CHECK_NE(NULL, node1);
- CHECK_EQ(1, node1->total_ticks());
- CHECK_EQ(1, node1->self_ticks());
- CHECK_EQ(NULL, token0_helper.Walk(&entry2));
- ProfileNode* node3 = token0_helper.Walk(&entry3);
- CHECK_NE(NULL, node3);
- CHECK_EQ(2, node3->total_ticks());
- CHECK_EQ(1, node3->self_ticks());
- ProfileNode* node3_1 = token0_helper.Walk(&entry3, &entry1);
- CHECK_NE(NULL, node3_1);
- CHECK_EQ(1, node3_1->total_ticks());
- CHECK_EQ(1, node3_1->self_ticks());
- CHECK_EQ(NULL, token0_helper.Walk(&entry3, &entry2));
- }
-
- {
- ProfileTree token1_tree;
- token1_tree.FilteredClone(&source_tree, token1);
- // Should be
- // {root,1,4,-1} -> {entry2,2,3,1} -> {entry4,1,1,inherits}
- // [child nodes referring to the same entry get merged and
- // their self times summed up]
- CHECK_EQ(4, token1_tree.root()->total_ticks());
- CHECK_EQ(1, token1_tree.root()->self_ticks());
- ProfileTreeTestHelper token1_helper(&token1_tree);
- CHECK_EQ(NULL, token1_helper.Walk(&entry1));
- CHECK_EQ(NULL, token1_helper.Walk(&entry3));
- ProfileNode* node2 = token1_helper.Walk(&entry2);
- CHECK_NE(NULL, node2);
- CHECK_EQ(3, node2->total_ticks());
- CHECK_EQ(2, node2->self_ticks());
- ProfileNode* node2_4 = token1_helper.Walk(&entry2, &entry4);
- CHECK_NE(NULL, node2_4);
- CHECK_EQ(1, node2_4->total_ticks());
- CHECK_EQ(1, node2_4->self_ticks());
- }
-
- {
- ProfileTree token2_tree;
- token2_tree.FilteredClone(&source_tree, token2);
- // Should be
- // {root,4,4,-1}
- // [no nodes, all ticks get migrated into root node]
- CHECK_EQ(4, token2_tree.root()->total_ticks());
- CHECK_EQ(4, token2_tree.root()->self_ticks());
- ProfileTreeTestHelper token2_helper(&token2_tree);
- CHECK_EQ(NULL, token2_helper.Walk(&entry1));
- CHECK_EQ(NULL, token2_helper.Walk(&entry2));
- CHECK_EQ(NULL, token2_helper.Walk(&entry3));
- }
-}
-
-
static inline i::Address ToAddress(int n) {
return reinterpret_cast<i::Address>(n);
}
+
TEST(CodeMapAddCode) {
CodeMap code_map;
- CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa");
- CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb");
- CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc");
- CodeEntry entry4(i::Logger::FUNCTION_TAG, "", "ddd");
+ CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
+ CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
+ CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
+ CodeEntry entry4(i::Logger::FUNCTION_TAG, "ddd");
code_map.AddCode(ToAddress(0x1500), &entry1, 0x200);
code_map.AddCode(ToAddress(0x1700), &entry2, 0x100);
code_map.AddCode(ToAddress(0x1900), &entry3, 0x50);
@@ -549,8 +412,8 @@ TEST(CodeMapAddCode) {
TEST(CodeMapMoveAndDeleteCode) {
CodeMap code_map;
- CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa");
- CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb");
+ CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
+ CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
code_map.AddCode(ToAddress(0x1500), &entry1, 0x200);
code_map.AddCode(ToAddress(0x1700), &entry2, 0x100);
CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1500)));
@@ -558,7 +421,7 @@ TEST(CodeMapMoveAndDeleteCode) {
code_map.MoveCode(ToAddress(0x1500), ToAddress(0x1700)); // Deprecate bbb.
CHECK_EQ(NULL, code_map.FindEntry(ToAddress(0x1500)));
CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1700)));
- CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc");
+ CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
code_map.AddCode(ToAddress(0x1750), &entry3, 0x100);
CHECK_EQ(NULL, code_map.FindEntry(ToAddress(0x1700)));
CHECK_EQ(&entry3, code_map.FindEntry(ToAddress(0x1750)));
@@ -622,8 +485,7 @@ TEST(RecordTickSample) {
sample3.frames_count = 2;
generator.RecordTickSample(sample3);
- CpuProfile* profile =
- profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1);
+ CpuProfile* profile = profiles.StopProfiling("", 1);
CHECK_NE(NULL, profile);
ProfileTreeTestHelper top_down_test_helper(profile->top_down());
CHECK_EQ(NULL, top_down_test_helper.Walk(entry2));
@@ -700,6 +562,7 @@ static void CheckNodeIds(ProfileNode* node, int* expectedId) {
}
}
+
TEST(SampleIds) {
TestSetup test_setup;
CpuProfilesCollection profiles;
@@ -735,8 +598,7 @@ TEST(SampleIds) {
sample3.frames_count = 2;
generator.RecordTickSample(sample3);
- CpuProfile* profile =
- profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1);
+ CpuProfile* profile = profiles.StopProfiling("", 1);
int nodeId = 1;
CheckNodeIds(profile->top_down()->root(), &nodeId);
CHECK_EQ(7, nodeId - 1);
@@ -765,8 +627,7 @@ TEST(NoSamples) {
sample1.frames_count = 1;
generator.RecordTickSample(sample1);
- CpuProfile* profile =
- profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1);
+ CpuProfile* profile = profiles.StopProfiling("", 1);
int nodeId = 1;
CheckNodeIds(profile->top_down()->root(), &nodeId);
CHECK_EQ(3, nodeId - 1);
@@ -860,7 +721,7 @@ TEST(RecordStackTraceAtStartProfiling) {
"a();\n"
"stopProfiling();");
CHECK_EQ(1, profiler->GetProfilesCount());
- CpuProfile* profile = profiler->GetProfile(NULL, 0);
+ CpuProfile* profile = profiler->GetProfile(0);
const ProfileTree* topDown = profile->top_down();
const ProfileNode* current = topDown->root();
const_cast<ProfileNode*>(current)->Print(0);
@@ -906,3 +767,118 @@ TEST(Issue51919) {
for (int i = 0; i < CpuProfilesCollection::kMaxSimultaneousProfiles; ++i)
i::DeleteArray(titles[i]);
}
+
+
+static const v8::CpuProfileNode* PickChild(const v8::CpuProfileNode* parent,
+ const char* name) {
+ for (int i = 0; i < parent->GetChildrenCount(); ++i) {
+ const v8::CpuProfileNode* child = parent->GetChild(i);
+ v8::String::AsciiValue function_name(child->GetFunctionName());
+ if (strcmp(*function_name, name) == 0) return child;
+ }
+ return NULL;
+}
+
+
+TEST(ProfileNodeScriptId) {
+ // This test does not pass with inlining enabled since inlined functions
+ // don't appear in the stack trace.
+ i::FLAG_use_inlining = false;
+
+ const char* extensions[] = { "v8/profiler" };
+ v8::ExtensionConfiguration config(1, extensions);
+ LocalContext env(&config);
+ v8::HandleScope hs(env->GetIsolate());
+
+ v8::CpuProfiler* profiler = env->GetIsolate()->GetCpuProfiler();
+ CHECK_EQ(0, profiler->GetProfileCount());
+ v8::Handle<v8::Script> script_a = v8::Script::Compile(v8::String::New(
+ "function a() { startProfiling(); }\n"));
+ script_a->Run();
+ v8::Handle<v8::Script> script_b = v8::Script::Compile(v8::String::New(
+ "function b() { a(); }\n"
+ "b();\n"
+ "stopProfiling();\n"));
+ script_b->Run();
+ CHECK_EQ(1, profiler->GetProfileCount());
+ const v8::CpuProfile* profile = profiler->GetCpuProfile(0);
+ const v8::CpuProfileNode* current = profile->GetTopDownRoot();
+ reinterpret_cast<ProfileNode*>(
+ const_cast<v8::CpuProfileNode*>(current))->Print(0);
+ // The tree should look like this:
+ // (root)
+ // (anonymous function)
+ // b
+ // a
+ // There can also be:
+ // startProfiling
+ // if the sampler managed to get a tick.
+ current = PickChild(current, i::ProfileGenerator::kAnonymousFunctionName);
+ CHECK_NE(NULL, const_cast<v8::CpuProfileNode*>(current));
+
+ current = PickChild(current, "b");
+ CHECK_NE(NULL, const_cast<v8::CpuProfileNode*>(current));
+ CHECK_EQ(script_b->GetId(), current->GetScriptId());
+
+ current = PickChild(current, "a");
+ CHECK_NE(NULL, const_cast<v8::CpuProfileNode*>(current));
+ CHECK_EQ(script_a->GetId(), current->GetScriptId());
+}
+
+
+
+
+static const char* line_number_test_source_existing_functions =
+"function foo_at_the_first_line() {\n"
+"}\n"
+"foo_at_the_first_line();\n"
+"function lazy_func_at_forth_line() {}\n";
+
+
+static const char* line_number_test_source_profile_time_functions =
+"// Empty first line\n"
+"function bar_at_the_second_line() {\n"
+" foo_at_the_first_line();\n"
+"}\n"
+"bar_at_the_second_line();\n"
+"function lazy_func_at_6th_line() {}";
+
+int GetFunctionLineNumber(LocalContext* env, const char* name) {
+ CpuProfiler* profiler = i::Isolate::Current()->cpu_profiler();
+ CodeMap* code_map = profiler->generator()->code_map();
+ i::Handle<i::JSFunction> func = v8::Utils::OpenHandle(
+ *v8::Local<v8::Function>::Cast(
+ (*(*env))->Global()->Get(v8_str(name))));
+ CodeEntry* func_entry = code_map->FindEntry(func->code()->address());
+ if (!func_entry)
+ FATAL(name);
+ return func_entry->line_number();
+}
+
+
+TEST(LineNumber) {
+ i::FLAG_use_inlining = false;
+
+ CcTest::InitializeVM();
+ LocalContext env;
+ i::Isolate* isolate = i::Isolate::Current();
+ TestSetup test_setup;
+
+ i::HandleScope scope(isolate);
+
+ CompileRun(line_number_test_source_existing_functions);
+
+ CpuProfiler* profiler = isolate->cpu_profiler();
+ profiler->StartProfiling("LineNumber");
+
+ CompileRun(line_number_test_source_profile_time_functions);
+
+ profiler->processor()->StopSynchronously();
+
+ CHECK_EQ(1, GetFunctionLineNumber(&env, "foo_at_the_first_line"));
+ CHECK_EQ(0, GetFunctionLineNumber(&env, "lazy_func_at_forth_line"));
+ CHECK_EQ(2, GetFunctionLineNumber(&env, "bar_at_the_second_line"));
+ CHECK_EQ(0, GetFunctionLineNumber(&env, "lazy_func_at_6th_line"));
+
+ profiler->StopProfiling("LineNumber");
+}
« no previous file with comments | « test/cctest/test-platform-tls.cc ('k') | test/cctest/test-regexp.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698