|  | // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 
|  | // for details. All rights reserved. Use of this source code is governed by a | 
|  | // BSD-style license that can be found in the LICENSE file. | 
|  |  | 
|  | #include "vm/compiler/cha.h" | 
|  | #include "platform/assert.h" | 
|  | #include "vm/class_finalizer.h" | 
|  | #include "vm/globals.h" | 
|  | #include "vm/resolver.h" | 
|  | #include "vm/symbols.h" | 
|  | #include "vm/unit_test.h" | 
|  |  | 
|  | namespace dart { | 
|  |  | 
|  | #define Z (thread->zone()) | 
|  |  | 
|  | TEST_CASE(ClassHierarchyAnalysis) { | 
|  | const char* kScriptChars = | 
|  | "class A {" | 
|  | "  foo() { }" | 
|  | "  bar() { }" | 
|  | "}\n" | 
|  | "class B extends A {" | 
|  | "}\n" | 
|  | "class C extends B {" | 
|  | "  foo() { }" | 
|  | "}\n" | 
|  | "class D extends A {" | 
|  | "  foo() { }" | 
|  | "  bar() { }" | 
|  | "}\n"; | 
|  |  | 
|  | TestCase::LoadTestScript(kScriptChars, NULL); | 
|  |  | 
|  | TransitionNativeToVM transition(thread); | 
|  | EXPECT(ClassFinalizer::ProcessPendingClasses()); | 
|  | const String& name = String::Handle(String::New(TestCase::url())); | 
|  | const Library& lib = Library::Handle(Library::LookupLibrary(thread, name)); | 
|  | EXPECT(!lib.IsNull()); | 
|  |  | 
|  | const Class& class_a = | 
|  | Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "A")))); | 
|  | EXPECT(!class_a.IsNull()); | 
|  | EXPECT(class_a.EnsureIsFinalized(thread) == Error::null()); | 
|  |  | 
|  | const Class& class_b = | 
|  | Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "B")))); | 
|  | EXPECT(!class_b.IsNull()); | 
|  |  | 
|  | const Class& class_c = | 
|  | Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "C")))); | 
|  | EXPECT(!class_c.IsNull()); | 
|  | EXPECT(class_c.EnsureIsFinalized(thread) == Error::null()); | 
|  |  | 
|  | const Class& class_d = | 
|  | Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "D")))); | 
|  | EXPECT(!class_d.IsNull()); | 
|  | EXPECT(class_d.EnsureIsFinalized(thread) == Error::null()); | 
|  |  | 
|  | const String& function_foo_name = String::Handle(String::New("foo")); | 
|  | const String& function_bar_name = String::Handle(String::New("bar")); | 
|  |  | 
|  | const Function& class_a_foo = Function::Handle( | 
|  | Resolver::ResolveDynamicFunction(Z, class_a, function_foo_name)); | 
|  | EXPECT(!class_a_foo.IsNull()); | 
|  |  | 
|  | const Function& class_a_bar = Function::Handle( | 
|  | Resolver::ResolveDynamicFunction(Z, class_a, function_bar_name)); | 
|  | EXPECT(!class_a_bar.IsNull()); | 
|  |  | 
|  | const Function& class_c_foo = Function::Handle( | 
|  | Resolver::ResolveDynamicFunction(Z, class_c, function_foo_name)); | 
|  | EXPECT(!class_c_foo.IsNull()); | 
|  |  | 
|  | const Function& class_d_foo = Function::Handle( | 
|  | Resolver::ResolveDynamicFunction(Z, class_d, function_foo_name)); | 
|  | EXPECT(!class_d_foo.IsNull()); | 
|  |  | 
|  | const Function& class_d_bar = Function::Handle( | 
|  | Resolver::ResolveDynamicFunction(Z, class_d, function_bar_name)); | 
|  | EXPECT(!class_d_bar.IsNull()); | 
|  |  | 
|  | CHA cha(thread); | 
|  |  | 
|  | EXPECT(cha.HasSubclasses(kInstanceCid)); | 
|  | EXPECT(!cha.HasSubclasses(kSmiCid)); | 
|  | EXPECT(!cha.HasSubclasses(kNullCid)); | 
|  |  | 
|  | EXPECT(CHA::HasSubclasses(class_a)); | 
|  | EXPECT(CHA::HasSubclasses(class_b)); | 
|  | EXPECT(!CHA::HasSubclasses(class_c)); | 
|  | cha.AddToGuardedClasses(class_c, /*subclass_count=*/0); | 
|  | EXPECT(!CHA::HasSubclasses(class_d)); | 
|  | cha.AddToGuardedClasses(class_d, /*subclass_count=*/0); | 
|  |  | 
|  | EXPECT(!cha.IsGuardedClass(class_a.id())); | 
|  | EXPECT(!cha.IsGuardedClass(class_b.id())); | 
|  | EXPECT(cha.IsGuardedClass(class_c.id())); | 
|  | EXPECT(cha.IsGuardedClass(class_d.id())); | 
|  |  | 
|  | const Class& closure_class = | 
|  | Class::Handle(IsolateGroup::Current()->object_store()->closure_class()); | 
|  | EXPECT(!cha.HasSubclasses(closure_class.id())); | 
|  | } | 
|  |  | 
|  | }  // namespace dart |