| Index: test/cctest/test-cpu-profiler.cc
|
| diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc
|
| index e2b6db0b963f673853e249caeda5e327c7f7d18a..c8f052416fe2aad4972d300833dd39c762a75c89 100644
|
| --- a/test/cctest/test-cpu-profiler.cc
|
| +++ b/test/cctest/test-cpu-profiler.cc
|
| @@ -56,6 +56,11 @@ static v8::Local<v8::Function> GetFunction(v8::Context* env, const char* name) {
|
| }
|
|
|
|
|
| +static const char* reason(const i::Deoptimizer::DeoptReason reason) {
|
| + return i::Deoptimizer::GetDeoptReason(reason);
|
| +}
|
| +
|
| +
|
| TEST(StartStop) {
|
| i::Isolate* isolate = CcTest::i_isolate();
|
| CpuProfilesCollection profiles(isolate->heap());
|
| @@ -455,8 +460,7 @@ static void CheckChildrenNames(const v8::CpuProfileNode* node,
|
| }
|
|
|
|
|
| -static const v8::CpuProfileNode* FindChild(v8::Isolate* isolate,
|
| - const v8::CpuProfileNode* node,
|
| +static const v8::CpuProfileNode* FindChild(const v8::CpuProfileNode* node,
|
| const char* name) {
|
| int count = node->GetChildrenCount();
|
| v8::Handle<v8::String> nameHandle = v8_str(name);
|
| @@ -468,10 +472,9 @@ static const v8::CpuProfileNode* FindChild(v8::Isolate* isolate,
|
| }
|
|
|
|
|
| -static const v8::CpuProfileNode* GetChild(v8::Isolate* isolate,
|
| - const v8::CpuProfileNode* node,
|
| +static const v8::CpuProfileNode* GetChild(const v8::CpuProfileNode* node,
|
| const char* name) {
|
| - const v8::CpuProfileNode* result = FindChild(isolate, node, name);
|
| + const v8::CpuProfileNode* result = FindChild(node, name);
|
| if (!result) {
|
| char buffer[100];
|
| i::SNPrintF(Vector<char>(buffer, arraysize(buffer)),
|
| @@ -482,26 +485,24 @@ static const v8::CpuProfileNode* GetChild(v8::Isolate* isolate,
|
| }
|
|
|
|
|
| -static void CheckSimpleBranch(v8::Isolate* isolate,
|
| - const v8::CpuProfileNode* node,
|
| +static void CheckSimpleBranch(const v8::CpuProfileNode* node,
|
| const char* names[], int length) {
|
| for (int i = 0; i < length; i++) {
|
| const char* name = names[i];
|
| - node = GetChild(isolate, node, name);
|
| + node = GetChild(node, name);
|
| int expectedChildrenCount = (i == length - 1) ? 0 : 1;
|
| CHECK_EQ(expectedChildrenCount, node->GetChildrenCount());
|
| }
|
| }
|
|
|
|
|
| -static const v8::CpuProfileNode* GetSimpleBranch(v8::Isolate* isolate,
|
| - const v8::CpuProfileNode* node,
|
| - const char* names[],
|
| - int length) {
|
| +static const ProfileNode* GetSimpleBranch(v8::CpuProfile* profile,
|
| + const char* names[], int length) {
|
| + const v8::CpuProfileNode* node = profile->GetTopDownRoot();
|
| for (int i = 0; i < length; i++) {
|
| - node = GetChild(isolate, node, names[i]);
|
| + node = GetChild(node, names[i]);
|
| }
|
| - return node;
|
| + return reinterpret_cast<const ProfileNode*>(node);
|
| }
|
|
|
|
|
| @@ -577,23 +578,18 @@ TEST(CollectCpuProfile) {
|
| names[2] = v8_str("start");
|
| CheckChildrenNames(root, names);
|
|
|
| - const v8::CpuProfileNode* startNode =
|
| - GetChild(env->GetIsolate(), root, "start");
|
| + const v8::CpuProfileNode* startNode = GetChild(root, "start");
|
| CHECK_EQ(1, startNode->GetChildrenCount());
|
|
|
| - const v8::CpuProfileNode* fooNode =
|
| - GetChild(env->GetIsolate(), startNode, "foo");
|
| + const v8::CpuProfileNode* fooNode = GetChild(startNode, "foo");
|
| CHECK_EQ(3, fooNode->GetChildrenCount());
|
|
|
| const char* barBranch[] = { "bar", "delay", "loop" };
|
| - CheckSimpleBranch(env->GetIsolate(), fooNode, barBranch,
|
| - arraysize(barBranch));
|
| + CheckSimpleBranch(fooNode, barBranch, arraysize(barBranch));
|
| const char* bazBranch[] = { "baz", "delay", "loop" };
|
| - CheckSimpleBranch(env->GetIsolate(), fooNode, bazBranch,
|
| - arraysize(bazBranch));
|
| + CheckSimpleBranch(fooNode, bazBranch, arraysize(bazBranch));
|
| const char* delayBranch[] = { "delay", "loop" };
|
| - CheckSimpleBranch(env->GetIsolate(), fooNode, delayBranch,
|
| - arraysize(delayBranch));
|
| + CheckSimpleBranch(fooNode, delayBranch, arraysize(delayBranch));
|
|
|
| profile->Delete();
|
| }
|
| @@ -650,11 +646,10 @@ TEST(HotDeoptNoFrameEntry) {
|
| names[2] = v8_str("start");
|
| CheckChildrenNames(root, names);
|
|
|
| - const v8::CpuProfileNode* startNode =
|
| - GetChild(env->GetIsolate(), root, "start");
|
| + const v8::CpuProfileNode* startNode = GetChild(root, "start");
|
| CHECK_EQ(1, startNode->GetChildrenCount());
|
|
|
| - GetChild(env->GetIsolate(), startNode, "foo");
|
| + GetChild(startNode, "foo");
|
|
|
| profile->Delete();
|
| }
|
| @@ -736,17 +731,15 @@ TEST(SampleWhenFrameIsNotSetup) {
|
| names[2] = v8_str("start");
|
| CheckChildrenNames(root, names);
|
|
|
| - const v8::CpuProfileNode* startNode =
|
| - FindChild(env->GetIsolate(), root, "start");
|
| + const v8::CpuProfileNode* startNode = FindChild(root, "start");
|
| // On slow machines there may be no meaningfull samples at all, skip the
|
| // check there.
|
| if (startNode && startNode->GetChildrenCount() > 0) {
|
| CHECK_EQ(1, startNode->GetChildrenCount());
|
| - const v8::CpuProfileNode* delayNode =
|
| - GetChild(env->GetIsolate(), startNode, "delay");
|
| + const v8::CpuProfileNode* delayNode = GetChild(startNode, "delay");
|
| if (delayNode->GetChildrenCount() > 0) {
|
| CHECK_EQ(1, delayNode->GetChildrenCount());
|
| - GetChild(env->GetIsolate(), delayNode, "loop");
|
| + GetChild(delayNode, "loop");
|
| }
|
| }
|
|
|
| @@ -842,10 +835,9 @@ TEST(NativeAccessorUninitializedIC) {
|
| RunProfiler(env.local(), function, args, arraysize(args), 180);
|
|
|
| const v8::CpuProfileNode* root = profile->GetTopDownRoot();
|
| - const v8::CpuProfileNode* startNode =
|
| - GetChild(isolate, root, "start");
|
| - GetChild(isolate, startNode, "get foo");
|
| - GetChild(isolate, startNode, "set foo");
|
| + const v8::CpuProfileNode* startNode = GetChild(root, "start");
|
| + GetChild(startNode, "get foo");
|
| + GetChild(startNode, "set foo");
|
|
|
| profile->Delete();
|
| }
|
| @@ -894,10 +886,9 @@ TEST(NativeAccessorMonomorphicIC) {
|
| RunProfiler(env.local(), function, args, arraysize(args), 200);
|
|
|
| const v8::CpuProfileNode* root = profile->GetTopDownRoot();
|
| - const v8::CpuProfileNode* startNode =
|
| - GetChild(isolate, root, "start");
|
| - GetChild(isolate, startNode, "get foo");
|
| - GetChild(isolate, startNode, "set foo");
|
| + const v8::CpuProfileNode* startNode = GetChild(root, "start");
|
| + GetChild(startNode, "get foo");
|
| + GetChild(startNode, "set foo");
|
|
|
| profile->Delete();
|
| }
|
| @@ -944,9 +935,8 @@ TEST(NativeMethodUninitializedIC) {
|
| RunProfiler(env.local(), function, args, arraysize(args), 100);
|
|
|
| const v8::CpuProfileNode* root = profile->GetTopDownRoot();
|
| - const v8::CpuProfileNode* startNode =
|
| - GetChild(isolate, root, "start");
|
| - GetChild(isolate, startNode, "fooMethod");
|
| + const v8::CpuProfileNode* startNode = GetChild(root, "start");
|
| + GetChild(startNode, "fooMethod");
|
|
|
| profile->Delete();
|
| }
|
| @@ -997,10 +987,9 @@ TEST(NativeMethodMonomorphicIC) {
|
| RunProfiler(env.local(), function, args, arraysize(args), 100);
|
|
|
| const v8::CpuProfileNode* root = profile->GetTopDownRoot();
|
| - GetChild(isolate, root, "start");
|
| - const v8::CpuProfileNode* startNode =
|
| - GetChild(isolate, root, "start");
|
| - GetChild(isolate, startNode, "fooMethod");
|
| + GetChild(root, "start");
|
| + const v8::CpuProfileNode* startNode = GetChild(root, "start");
|
| + GetChild(startNode, "fooMethod");
|
|
|
| profile->Delete();
|
| }
|
| @@ -1034,9 +1023,8 @@ TEST(BoundFunctionCall) {
|
| // Don't allow |foo| node to be at the top level.
|
| CheckChildrenNames(root, names);
|
|
|
| - const v8::CpuProfileNode* startNode =
|
| - GetChild(env->GetIsolate(), root, "start");
|
| - GetChild(env->GetIsolate(), startNode, "foo");
|
| + const v8::CpuProfileNode* startNode = GetChild(root, "start");
|
| + GetChild(startNode, "foo");
|
|
|
| profile->Delete();
|
| }
|
| @@ -1197,8 +1185,7 @@ TEST(FunctionCallSample) {
|
| // won't be |start| node in the profiles.
|
| bool is_gc_stress_testing =
|
| (i::FLAG_gc_interval != -1) || i::FLAG_stress_compaction;
|
| - const v8::CpuProfileNode* startNode =
|
| - FindChild(env->GetIsolate(), root, "start");
|
| + const v8::CpuProfileNode* startNode = FindChild(root, "start");
|
| CHECK(is_gc_stress_testing || startNode);
|
| if (startNode) {
|
| ScopedVector<v8::Handle<v8::String> > names(2);
|
| @@ -1207,8 +1194,8 @@ TEST(FunctionCallSample) {
|
| CheckChildrenNames(startNode, names);
|
| }
|
|
|
| - const v8::CpuProfileNode* unresolvedNode = FindChild(
|
| - env->GetIsolate(), root, i::ProfileGenerator::kUnresolvedFunctionName);
|
| + const v8::CpuProfileNode* unresolvedNode =
|
| + FindChild(root, i::ProfileGenerator::kUnresolvedFunctionName);
|
| if (unresolvedNode) {
|
| ScopedVector<v8::Handle<v8::String> > names(1);
|
| names[0] = v8_str("call");
|
| @@ -1270,8 +1257,7 @@ TEST(FunctionApplySample) {
|
| CheckChildrenNames(root, names);
|
| }
|
|
|
| - const v8::CpuProfileNode* startNode =
|
| - FindChild(env->GetIsolate(), root, "start");
|
| + const v8::CpuProfileNode* startNode = FindChild(root, "start");
|
| if (startNode) {
|
| {
|
| ScopedVector<v8::Handle<v8::String> > names(2);
|
| @@ -1280,8 +1266,7 @@ TEST(FunctionApplySample) {
|
| CheckChildrenNames(startNode, names);
|
| }
|
|
|
| - const v8::CpuProfileNode* testNode =
|
| - FindChild(env->GetIsolate(), startNode, "test");
|
| + const v8::CpuProfileNode* testNode = FindChild(startNode, "test");
|
| if (testNode) {
|
| ScopedVector<v8::Handle<v8::String> > names(3);
|
| names[0] = v8_str("bar");
|
| @@ -1293,12 +1278,11 @@ TEST(FunctionApplySample) {
|
| }
|
|
|
| if (const v8::CpuProfileNode* unresolvedNode =
|
| - FindChild(env->GetIsolate(), startNode,
|
| - ProfileGenerator::kUnresolvedFunctionName)) {
|
| + FindChild(startNode, ProfileGenerator::kUnresolvedFunctionName)) {
|
| ScopedVector<v8::Handle<v8::String> > names(1);
|
| names[0] = v8_str("apply");
|
| CheckChildrenNames(unresolvedNode, names);
|
| - GetChild(env->GetIsolate(), unresolvedNode, "apply");
|
| + GetChild(unresolvedNode, "apply");
|
| }
|
| }
|
|
|
| @@ -1354,10 +1338,9 @@ TEST(CpuProfileDeepStack) {
|
| CheckChildrenNames(root, names);
|
| }
|
|
|
| - const v8::CpuProfileNode* node =
|
| - GetChild(env->GetIsolate(), root, "start");
|
| + const v8::CpuProfileNode* node = GetChild(root, "start");
|
| for (int i = 0; i < 250; ++i) {
|
| - node = GetChild(env->GetIsolate(), node, "foo");
|
| + node = GetChild(node, "foo");
|
| }
|
| // TODO(alph):
|
| // In theory there must be one more 'foo' and a 'startProfiling' nodes,
|
| @@ -1419,18 +1402,16 @@ TEST(JsNativeJsSample) {
|
| CheckChildrenNames(root, names);
|
| }
|
|
|
| - const v8::CpuProfileNode* startNode =
|
| - GetChild(env->GetIsolate(), root, "start");
|
| + const v8::CpuProfileNode* startNode = GetChild(root, "start");
|
| CHECK_EQ(1, startNode->GetChildrenCount());
|
| const v8::CpuProfileNode* nativeFunctionNode =
|
| - GetChild(env->GetIsolate(), startNode, "CallJsFunction");
|
| + GetChild(startNode, "CallJsFunction");
|
|
|
| CHECK_EQ(1, nativeFunctionNode->GetChildrenCount());
|
| - const v8::CpuProfileNode* barNode =
|
| - GetChild(env->GetIsolate(), nativeFunctionNode, "bar");
|
| + const v8::CpuProfileNode* barNode = GetChild(nativeFunctionNode, "bar");
|
|
|
| CHECK_EQ(1, barNode->GetChildrenCount());
|
| - GetChild(env->GetIsolate(), barNode, "foo");
|
| + GetChild(barNode, "foo");
|
|
|
| profile->Delete();
|
| }
|
| @@ -1481,22 +1462,20 @@ TEST(JsNativeJsRuntimeJsSample) {
|
| names[2] = v8_str("start");
|
| CheckChildrenNames(root, names);
|
|
|
| - const v8::CpuProfileNode* startNode =
|
| - GetChild(env->GetIsolate(), root, "start");
|
| + const v8::CpuProfileNode* startNode = GetChild(root, "start");
|
| CHECK_EQ(1, startNode->GetChildrenCount());
|
| const v8::CpuProfileNode* nativeFunctionNode =
|
| - GetChild(env->GetIsolate(), startNode, "CallJsFunction");
|
| + GetChild(startNode, "CallJsFunction");
|
|
|
| CHECK_EQ(1, nativeFunctionNode->GetChildrenCount());
|
| - const v8::CpuProfileNode* barNode =
|
| - GetChild(env->GetIsolate(), nativeFunctionNode, "bar");
|
| + const v8::CpuProfileNode* barNode = GetChild(nativeFunctionNode, "bar");
|
|
|
| // The child is in fact a bound foo.
|
| // A bound function has a wrapper that may make calls to
|
| // other functions e.g. "get length".
|
| CHECK_LE(1, barNode->GetChildrenCount());
|
| CHECK_GE(2, barNode->GetChildrenCount());
|
| - GetChild(env->GetIsolate(), barNode, "foo");
|
| + GetChild(barNode, "foo");
|
|
|
| profile->Delete();
|
| }
|
| @@ -1560,22 +1539,19 @@ TEST(JsNative1JsNative2JsSample) {
|
| names[2] = v8_str("start");
|
| CheckChildrenNames(root, names);
|
|
|
| - const v8::CpuProfileNode* startNode =
|
| - GetChild(env->GetIsolate(), root, "start");
|
| + const v8::CpuProfileNode* startNode = GetChild(root, "start");
|
| CHECK_EQ(1, startNode->GetChildrenCount());
|
| const v8::CpuProfileNode* nativeNode1 =
|
| - GetChild(env->GetIsolate(), startNode, "CallJsFunction1");
|
| + GetChild(startNode, "CallJsFunction1");
|
|
|
| CHECK_EQ(1, nativeNode1->GetChildrenCount());
|
| - const v8::CpuProfileNode* barNode =
|
| - GetChild(env->GetIsolate(), nativeNode1, "bar");
|
| + const v8::CpuProfileNode* barNode = GetChild(nativeNode1, "bar");
|
|
|
| CHECK_EQ(1, barNode->GetChildrenCount());
|
| - const v8::CpuProfileNode* nativeNode2 =
|
| - GetChild(env->GetIsolate(), barNode, "CallJsFunction2");
|
| + const v8::CpuProfileNode* nativeNode2 = GetChild(barNode, "CallJsFunction2");
|
|
|
| CHECK_EQ(1, nativeNode2->GetChildrenCount());
|
| - GetChild(env->GetIsolate(), nativeNode2, "foo");
|
| + GetChild(nativeNode2, "foo");
|
|
|
| profile->Delete();
|
| }
|
| @@ -1620,12 +1596,12 @@ TEST(IdleTime) {
|
| CheckChildrenNames(root, names);
|
|
|
| const v8::CpuProfileNode* programNode =
|
| - GetChild(env->GetIsolate(), root, ProfileGenerator::kProgramEntryName);
|
| + GetChild(root, ProfileGenerator::kProgramEntryName);
|
| CHECK_EQ(0, programNode->GetChildrenCount());
|
| CHECK_GE(programNode->GetHitCount(), 3u);
|
|
|
| const v8::CpuProfileNode* idleNode =
|
| - GetChild(env->GetIsolate(), root, ProfileGenerator::kIdleEntryName);
|
| + GetChild(root, ProfileGenerator::kIdleEntryName);
|
| CHECK_EQ(0, idleNode->GetChildrenCount());
|
| CHECK_GE(idleNode->GetHitCount(), 3u);
|
|
|
| @@ -1672,16 +1648,16 @@ TEST(FunctionDetails) {
|
| // 0 foo 18 #4 TryCatchStatement script_a:2
|
| // 1 bar 18 #5 no reason script_a:3
|
| const v8::CpuProfileNode* root = profile->GetTopDownRoot();
|
| - const v8::CpuProfileNode* script = GetChild(env->GetIsolate(), root, "");
|
| + const v8::CpuProfileNode* script = GetChild(root, "");
|
| CheckFunctionDetails(env->GetIsolate(), script, "", "script_b",
|
| script_b->GetUnboundScript()->GetId(), 1, 1);
|
| - const v8::CpuProfileNode* baz = GetChild(env->GetIsolate(), script, "baz");
|
| + const v8::CpuProfileNode* baz = GetChild(script, "baz");
|
| CheckFunctionDetails(env->GetIsolate(), baz, "baz", "script_b",
|
| script_b->GetUnboundScript()->GetId(), 3, 16);
|
| - const v8::CpuProfileNode* foo = GetChild(env->GetIsolate(), baz, "foo");
|
| + const v8::CpuProfileNode* foo = GetChild(baz, "foo");
|
| CheckFunctionDetails(env->GetIsolate(), foo, "foo", "script_a",
|
| script_a->GetUnboundScript()->GetId(), 2, 1);
|
| - const v8::CpuProfileNode* bar = GetChild(env->GetIsolate(), foo, "bar");
|
| + const v8::CpuProfileNode* bar = GetChild(foo, "bar");
|
| CheckFunctionDetails(env->GetIsolate(), bar, "bar", "script_a",
|
| script_a->GetUnboundScript()->GetId(), 3, 14);
|
| }
|
| @@ -1720,39 +1696,7 @@ TEST(DontStopOnFinishedProfileDelete) {
|
| }
|
|
|
|
|
| -static const char* collect_deopt_events_test_source =
|
| - "function opt_function(left, right, depth) {\n"
|
| - " if (depth) return opt_function(left, right, depth - 1);\n"
|
| - "\n"
|
| - " var k = left / 10;\n"
|
| - " var r = 10 / right;\n"
|
| - " return k + r;"
|
| - "}\n"
|
| - "\n"
|
| - "function test(left, right) {\n"
|
| - " return opt_function(left, right, 1);\n"
|
| - "}\n"
|
| - "\n"
|
| - "startProfiling();\n"
|
| - "\n"
|
| - "test(10, 10);\n"
|
| - "\n"
|
| - "%OptimizeFunctionOnNextCall(opt_function)\n"
|
| - "\n"
|
| - "test(10, 10);\n"
|
| - "\n"
|
| - "test(undefined, 10);\n"
|
| - "\n"
|
| - "%OptimizeFunctionOnNextCall(opt_function)\n"
|
| - "\n"
|
| - "test(10, 10);\n"
|
| - "\n"
|
| - "test(10, 0);\n"
|
| - "\n"
|
| - "stopProfiling();\n"
|
| - "\n";
|
| -
|
| -
|
| +// deopt at top function
|
| TEST(CollectDeoptEvents) {
|
| if (!CcTest::i_isolate()->use_crankshaft() || i::FLAG_always_opt) return;
|
| i::FLAG_allow_natives_syntax = true;
|
| @@ -1763,20 +1707,49 @@ TEST(CollectDeoptEvents) {
|
| v8::CpuProfiler* profiler = isolate->GetCpuProfiler();
|
| i::CpuProfiler* iprofiler = reinterpret_cast<i::CpuProfiler*>(profiler);
|
|
|
| - v8::Script::Compile(v8_str(collect_deopt_events_test_source))->Run();
|
| + const char* source =
|
| + "function opt_function(left, right, depth) {\n"
|
| + " if (depth) return opt_function(left, right, depth - 1);\n"
|
| + "\n"
|
| + " var k = left / 10;\n"
|
| + " var r = 10 / right;\n"
|
| + " return k + r;"
|
| + "}\n"
|
| + "\n"
|
| + "function test(left, right) {\n"
|
| + " return opt_function(left, right, 1);\n"
|
| + "}\n"
|
| + "\n"
|
| + "startProfiling();\n"
|
| + "\n"
|
| + "test(10, 10);\n"
|
| + "\n"
|
| + "%OptimizeFunctionOnNextCall(opt_function)\n"
|
| + "\n"
|
| + "test(10, 10);\n"
|
| + "\n"
|
| + "test(undefined, 10);\n"
|
| + "\n"
|
| + "%OptimizeFunctionOnNextCall(opt_function)\n"
|
| + "\n"
|
| + "test(10, 10);\n"
|
| + "\n"
|
| + "test(10, 0);\n"
|
| + "\n"
|
| + "stopProfiling();\n"
|
| + "\n";
|
| +
|
| + v8::Script::Compile(v8_str(source))->Run();
|
| i::CpuProfile* iprofile = iprofiler->GetProfile(0);
|
| iprofile->Print();
|
| v8::CpuProfile* profile = reinterpret_cast<v8::CpuProfile*>(iprofile);
|
| const char* branch[] = {"", "test", "opt_function", "opt_function"};
|
| - const v8::CpuProfileNode* opt_function = GetSimpleBranch(
|
| - env->GetIsolate(), profile->GetTopDownRoot(), branch, arraysize(branch));
|
| - CHECK(opt_function);
|
| - const i::ProfileNode* iopt_function =
|
| - reinterpret_cast<const i::ProfileNode*>(opt_function);
|
| + const ProfileNode* iopt_function =
|
| + GetSimpleBranch(profile, branch, arraysize(branch));
|
| CHECK_EQ(2, iopt_function->deopt_infos().length());
|
| - CHECK_EQ(i::Deoptimizer::GetDeoptReason(i::Deoptimizer::kNotAHeapNumber),
|
| + CHECK_EQ(reason(i::Deoptimizer::kNotAHeapNumber),
|
| iopt_function->deopt_infos()[0].deopt_reason);
|
| - CHECK_EQ(i::Deoptimizer::GetDeoptReason(i::Deoptimizer::kDivisionByZero),
|
| + CHECK_EQ(reason(i::Deoptimizer::kDivisionByZero),
|
| iopt_function->deopt_infos()[1].deopt_reason);
|
| iprofiler->DeleteProfile(iprofile);
|
| }
|
|
|