1// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/compiler/cha.h"
6#include "platform/assert.h"
7#include "vm/class_finalizer.h"
8#include "vm/globals.h"
9#include "vm/symbols.h"
10#include "vm/unit_test.h"
11
12namespace dart {
13
14TEST_CASE(ClassHierarchyAnalysis) {
15 const char* kScriptChars =
16 "class A {"
17 " foo() { }"
18 " bar() { }"
19 "}\n"
20 "class B extends A {"
21 "}\n"
22 "class C extends B {"
23 " foo() { }"
24 "}\n"
25 "class D extends A {"
26 " foo() { }"
27 " bar() { }"
28 "}\n";
29
30 TestCase::LoadTestScript(kScriptChars, NULL);
31
32 TransitionNativeToVM transition(thread);
33 EXPECT(ClassFinalizer::ProcessPendingClasses());
34 const String& name = String::Handle(String::New(TestCase::url()));
35 const Library& lib = Library::Handle(Library::LookupLibrary(thread, name));
36 EXPECT(!lib.IsNull());
37
38 const Class& class_a =
39 Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "A"))));
40 EXPECT(!class_a.IsNull());
41
42 const Class& class_b =
43 Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "B"))));
44 EXPECT(!class_b.IsNull());
45
46 const Class& class_c =
47 Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "C"))));
48 EXPECT(!class_c.IsNull());
49
50 const Class& class_d =
51 Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "D"))));
52 EXPECT(!class_d.IsNull());
53
54 const String& function_foo_name = String::Handle(String::New("foo"));
55 const String& function_bar_name = String::Handle(String::New("bar"));
56
57 const Function& class_a_foo =
58 Function::Handle(class_a.LookupDynamicFunction(function_foo_name));
59 EXPECT(!class_a_foo.IsNull());
60
61 const Function& class_a_bar =
62 Function::Handle(class_a.LookupDynamicFunction(function_bar_name));
63 EXPECT(!class_a_bar.IsNull());
64
65 const Function& class_c_foo =
66 Function::Handle(class_c.LookupDynamicFunction(function_foo_name));
67 EXPECT(!class_c_foo.IsNull());
68
69 const Function& class_d_foo =
70 Function::Handle(class_d.LookupDynamicFunction(function_foo_name));
71 EXPECT(!class_d_foo.IsNull());
72
73 const Function& class_d_bar =
74 Function::Handle(class_d.LookupDynamicFunction(function_bar_name));
75 EXPECT(!class_d_bar.IsNull());
76
77 CHA cha(Thread::Current());
78
79 EXPECT(cha.HasSubclasses(kInstanceCid));
80 EXPECT(!cha.HasSubclasses(kSmiCid));
81 EXPECT(!cha.HasSubclasses(kNullCid));
82
83 EXPECT(CHA::HasSubclasses(class_a));
84 EXPECT(CHA::HasSubclasses(class_b));
85 EXPECT(!CHA::HasSubclasses(class_c));
86 cha.AddToGuardedClasses(class_c, /*subclass_count=*/0);
87 EXPECT(!CHA::HasSubclasses(class_d));
88 cha.AddToGuardedClasses(class_d, /*subclass_count=*/0);
89
90 EXPECT(!cha.IsGuardedClass(class_a.id()));
91 EXPECT(!cha.IsGuardedClass(class_b.id()));
92 EXPECT(cha.IsGuardedClass(class_c.id()));
93 EXPECT(cha.IsGuardedClass(class_d.id()));
94
95 const Class& closure_class =
96 Class::Handle(Isolate::Current()->object_store()->closure_class());
97 EXPECT(!cha.HasSubclasses(closure_class.id()));
98}
99
100} // namespace dart
101