// 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