Revert r1380 that is breaking frog.

Review URL: http://codereview.chromium.org//8509031

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@1382 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
regis@google.com 2011-11-10 01:39:06 +00:00
parent 1e203b2dc9
commit a6282231eb
16 changed files with 254 additions and 352 deletions

View file

@ -148,7 +148,7 @@ static void RunIsolate(uword parameter) {
if (setjmp(*jump.Set()) == 0) {
Zone zone;
HandleScope handle_scope;
ASSERT(ClassFinalizer::AllClassesFinalized());
ASSERT(ClassFinalizer::FinalizePendingClasses());
// Lookup the target class by name, create an instance and call the run
// method.
const String& lib_name = String::Handle(String::NewSymbol(library_url));
@ -223,7 +223,7 @@ static bool CheckArguments(const char* library_url, const char* class_name) {
Zone zone;
HandleScope handle_scope;
String& name = String::Handle();
if (!ClassFinalizer::FinalizeAllClasses()) {
if (!ClassFinalizer::FinalizePendingClasses()) {
return false;
}
// Lookup the target class by name, create an instance and call the run

View file

@ -18,27 +18,8 @@ DEFINE_FLAG(bool, verify_implements, false,
"Verify that all classes implement their interface.");
DECLARE_FLAG(bool, enable_type_checks);
void ClassFinalizer::ExpectClassesToFinalize() {
if (!IsExpectingClassesToFinalize()) {
ObjectStore* object_store = Isolate::Current()->object_store();
object_store->set_pending_classes(Array::Handle(Array::Empty()));
ASSERT(IsExpectingClassesToFinalize());
}
}
bool ClassFinalizer::IsExpectingClassesToFinalize() {
ObjectStore* object_store = Isolate::Current()->object_store();
const Array& classes = Array::Handle(object_store->pending_classes());
return !classes.IsNull();
}
void ClassFinalizer::AddClassesToFinalize(
void ClassFinalizer::AddPendingClasses(
const GrowableArray<const Class*>& classes) {
// ExpectClassesToFinalize() must be called prior to calling
// AddClassesToFinalize().
ASSERT(IsExpectingClassesToFinalize());
if (!classes.is_empty()) {
ObjectStore* object_store = Isolate::Current()->object_store();
const Array& old_array = Array::Handle(object_store->pending_classes());
@ -50,15 +31,21 @@ void ClassFinalizer::AddClassesToFinalize(
new_array.SetAt(i + old_length, *classes[i]);
}
object_store->set_pending_classes(new_array);
ASSERT(IsExpectingClassesToFinalize());
}
}
bool ClassFinalizer::AllClassesFinalized() {
ObjectStore* object_store = Isolate::Current()->object_store();
const Array& classes = Array::Handle(object_store->pending_classes());
return classes.Length() == 0;
}
// Class finalization occurs:
// a) when bootstrap process completes (VerifyBootstrapClasses).
// b) after the user classes are loaded (dart_api).
bool ClassFinalizer::FinalizeAllClasses() {
bool ClassFinalizer::FinalizePendingClasses() {
bool retval = true;
Isolate* isolate = Isolate::Current();
ASSERT(isolate != NULL);
@ -72,11 +59,10 @@ bool ClassFinalizer::FinalizeAllClasses() {
isolate->set_long_jump_base(&jump);
if (setjmp(*jump.Set()) == 0) {
const Array& class_array = Array::Handle(object_store->pending_classes());
const intptr_t num_pending_classes =
class_array.IsNull() ? 0 : class_array.Length();
ASSERT(!class_array.IsNull());
Class& cls = Class::Handle();
// First resolve all superclasses.
for (intptr_t i = 0; i < num_pending_classes; i++) {
for (intptr_t i = 0; i < class_array.Length(); i++) {
cls ^= class_array.At(i);
if (FLAG_trace_class_finalization) {
OS::Print("Resolving super and default: %s\n", cls.ToCString());
@ -87,18 +73,18 @@ bool ClassFinalizer::FinalizeAllClasses() {
}
}
// Finalize all classes.
for (intptr_t i = 0; i < num_pending_classes; i++) {
for (intptr_t i = 0; i < class_array.Length(); i++) {
cls ^= class_array.At(i);
FinalizeClass(cls);
}
if (FLAG_print_classes) {
for (intptr_t i = 0; i < num_pending_classes; i++) {
for (intptr_t i = 0; i < class_array.Length(); i++) {
cls ^= class_array.At(i);
PrintClassInformation(cls);
}
}
if (FLAG_verify_implements) {
for (intptr_t i = 0; i < num_pending_classes; i++) {
for (intptr_t i = 0; i < class_array.Length(); i++) {
cls ^= class_array.At(i);
if (!cls.is_interface()) {
VerifyClassImplements(cls);
@ -106,8 +92,7 @@ bool ClassFinalizer::FinalizeAllClasses() {
}
}
// Clear pending classes array.
object_store->set_pending_classes(Array::Handle());
ASSERT(!IsExpectingClassesToFinalize());
object_store->set_pending_classes(Array::Handle(Array::Empty()));
// Check to ensure there are no duplicate definitions in the library
// hierarchy.
@ -244,7 +229,7 @@ void ClassFinalizer::VerifyBootstrapClasses() {
}
// Finalize classes that aren't pre-finalized by Object::Init().
if (!FinalizeAllClasses()) {
if (!FinalizePendingClasses()) {
// TODO(srdjan): Exit like a real VM instead.
const String& err = String::Handle(object_store->sticky_error());
OS::PrintErr("Could not verify bootstrap classes : %s\n", err.ToCString());
@ -257,39 +242,6 @@ void ClassFinalizer::VerifyBootstrapClasses() {
}
// Resolve unresolved_class in the library of cls.
RawClass* ClassFinalizer::ResolveClass(
const Class& cls, const UnresolvedClass& unresolved_class) {
Library& lib = Library::Handle();
if (unresolved_class.qualifier() == String::null()) {
lib = cls.library();
} else {
const String& qualifier = String::Handle(unresolved_class.qualifier());
LibraryPrefix& lib_prefix = LibraryPrefix::Handle();
lib_prefix = cls.LookupLibraryPrefix(qualifier);
if (lib_prefix.IsNull()) {
const Script& script = Script::Handle(cls.script());
ReportError(script, unresolved_class.token_index(),
"cannot resolve library prefix '%s' from '%s'.\n",
String::Handle(unresolved_class.Name()).ToCString(),
String::Handle(cls.Name()).ToCString());
}
lib = lib_prefix.library();
}
ASSERT(!lib.IsNull());
const String& class_name = String::Handle(unresolved_class.ident());
const Class& resolved_class = Class::Handle(lib.LookupClass(class_name));
if (resolved_class.IsNull()) {
const Script& script = Script::Handle(cls.script());
ReportError(script, unresolved_class.token_index(),
"cannot resolve class name '%s' from '%s'.\n",
String::Handle(unresolved_class.Name()).ToCString(),
String::Handle(cls.Name()).ToCString());
}
return resolved_class.raw();
}
// Resolve unresolved superclasses (String -> Class).
void ClassFinalizer::ResolveSuperClass(const Class& cls) {
if (cls.is_finalized()) {
@ -301,13 +253,6 @@ void ClassFinalizer::ResolveSuperClass(const Class& cls) {
}
// Resolve failures lead to a longjmp.
super_type = ResolveType(cls, super_type);
if (super_type.IsTypeParameter()) {
String& class_name = String::Handle(cls.Name());
String& type_parameter_name = String::Handle(super_type.Name());
ReportError("'%s' cannot extend or implement type parameter '%s'.\n",
class_name.ToCString(),
type_parameter_name.ToCString());
}
cls.set_super_type(super_type);
const Class& super_class = Class::Handle(super_type.type_class());
if (cls.is_interface() != super_class.is_interface()) {
@ -409,9 +354,31 @@ RawType* ClassFinalizer::ResolveType(const Class& cls, const Type& type) {
}
// Lookup the type class.
const Class& type_class =
Class::Handle(ResolveClass(cls, unresolved_class));
Class& type_class = Class::Handle();
Library& lib = Library::Handle();
if (unresolved_class.qualifier() == String::null()) {
lib = cls.library();
} else {
const String& qualifier = String::Handle(unresolved_class.qualifier());
LibraryPrefix& lib_prefix = LibraryPrefix::Handle();
lib_prefix = cls.LookupLibraryPrefix(qualifier);
if (lib_prefix.IsNull()) {
const Script& script = Script::Handle(cls.script());
ReportError(script, unresolved_class.token_index(),
"cannot resolve name '%s'\n",
String::Handle(unresolved_class.Name()).ToCString());
}
lib = lib_prefix.library();
}
ASSERT(!lib.IsNull());
type_class = lib.LookupClass(type_class_name);
if (type_class.IsNull()) {
const Script& script = Script::Handle(cls.script());
ReportError(script, unresolved_class.token_index(),
"cannot resolve class name '%s' from '%s'\n",
String::Handle(unresolved_class.Name()).ToCString(),
String::Handle(cls.Name()).ToCString());
}
// Replace unresolved class with resolved type class.
ASSERT(type.IsParameterizedType());
ParameterizedType& parameterized_type = ParameterizedType::Handle();
@ -539,18 +506,10 @@ RawType* ClassFinalizer::FinalizeType(const Type& type) {
}
// The type class does not need to be finalized in order to finalize the type,
// however, it must at least be resolved (this was done as part of resolving
// the type itself, a precondition to calling FinalizeType) and the upper
// bounds of its type parameters must be finalized (done here).
// however, it must at least be resolved. This was done as part of resolving
// the type itself.
Class& type_class = Class::Handle(parameterized_type.type_class());
// If the type class is a signature class, finalize it, thereby finalizing the
// result and parameter types of its signature function.
// Do this before marking this type as finalized in order to detect cycles.
if (type_class.IsSignatureClass()) {
FinalizeClass(type_class);
}
// The finalized type argument vector needs num_type_arguments types.
const intptr_t num_type_arguments = type_class.NumTypeArguments();
// The type class has num_type_parameters type parameters.
@ -586,11 +545,14 @@ RawType* ClassFinalizer::FinalizeType(const Type& type) {
FinalizeTypeArguments(type_class, full_arguments);
parameterized_type.set_arguments(full_arguments);
}
// Mark the type as finalized before finalizing the upper bounds, because
// cycles via upper bounds are legal at compile time.
parameterized_type.set_is_finalized();
ResolveAndFinalizeUpperBounds(type_class);
// If the type is a function type, finalize the result and parameter types.
if (type_class.IsSignatureClass()) {
ResolveAndFinalizeSignature(
type_class, Function::Handle(type_class.signature_function()));
}
parameterized_type.set_is_finalized();
return parameterized_type.Canonicalize();
}
@ -603,15 +565,7 @@ RawType* ClassFinalizer::FinalizeAndCanonicalizeType(const Type& type,
LongJump jump;
isolate->set_long_jump_base(&jump);
if (setjmp(*jump.Set()) == 0) {
Type& canonical_type = Type::Handle();
if (type.IsSignatureType() && !AllClassesFinalized()) {
// Postpone the finalization of this signature type and class.
GrowableArray<const Class*> classes;
classes.Add(&Class::ZoneHandle(type.type_class()));
ClassFinalizer::AddClassesToFinalize(classes);
} else {
canonical_type = FinalizeType(type);
}
const Type& canonical_type = Type::Handle(FinalizeType(type));
isolate->set_long_jump_base(base);
*errmsg = String::null();
return canonical_type.raw();
@ -626,6 +580,11 @@ RawType* ClassFinalizer::FinalizeAndCanonicalizeType(const Type& type,
}
// Top level function signatures are canonicalized, added to the library class
// dictionary, and finalized with other library classes and interfaces.
// Function signatures used as type of a local variable or of a local function
// are canonicalized and finalized upon creation, since all the types they
// reference are already resolved.
void ClassFinalizer::ResolveAndFinalizeSignature(const Class& cls,
const Function& function) {
// Resolve result type.
@ -685,23 +644,6 @@ static RawClass* FindSuperOwnerOfFunction(const Class& cls,
}
void ClassFinalizer::ResolveAndFinalizeUpperBounds(const Class& cls) {
const intptr_t num_type_params = cls.NumTypeParameters();
Type& type_extends = Type::Handle();
const TypeArguments& extends_array =
TypeArguments::Handle(cls.type_parameter_extends());
ASSERT((extends_array.IsNull() && (num_type_params == 0)) ||
(extends_array.Length() == num_type_params));
for (intptr_t i = 0; i < num_type_params; i++) {
type_extends = extends_array.TypeAt(i);
type_extends = ResolveType(cls, type_extends);
extends_array.SetTypeAt(i, type_extends);
type_extends = FinalizeType(type_extends);
extends_array.SetTypeAt(i, type_extends);
}
}
void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) {
// Note that getters and setters are explicitly listed as such in the list of
// functions of a class, so we do not need to consider fields as implicitly
@ -835,6 +777,13 @@ void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) {
}
}
}
// Resolve the signature type if this class is a signature class.
if (cls.IsSignatureClass()) {
Type& signature_type = Type::Handle(cls.SignatureType());
signature_type = FinalizeType(signature_type);
// Signature types are canonicalized by default.
ASSERT(signature_type.raw() == cls.SignatureType());
}
}
@ -884,25 +833,9 @@ void ClassFinalizer::FinalizeClass(const Class& cls) {
interface_type = FinalizeType(interface_type);
interface_types.SetAt(i, interface_type);
}
// Mark as finalized before resolving type parameter upper bounds and member
// types in order to break cycles.
// Mark as finalized before resolving member types in order to break cycles.
cls.Finalize();
ResolveAndFinalizeUpperBounds(cls);
ResolveAndFinalizeMemberTypes(cls);
if (cls.IsSignatureClass()) {
// Finalize the signature type of this signature class.
Type& signature_type = Type::Handle(cls.SignatureType());
signature_type = FinalizeType(signature_type);
// Signature types are canonicalized by default.
ASSERT(signature_type.raw() == cls.SignatureType());
// Resolve and finalize the result and parameter types of the signature
// function of this signature class.
ResolveAndFinalizeSignature(cls,
Function::Handle(cls.signature_function()));
}
// Run additional checks after all types are finalized.
if (cls.is_const()) {
CheckForLegalConstClass(cls);
@ -1031,6 +964,8 @@ void ClassFinalizer::ResolveInterfaces(const Class& cls,
String::Handle(cls.Name()).ToCString(),
String::Handle(interface_class.Name()).ToCString());
}
// TODO(regis): We also need to prevent extending classes Smi, Mint,
// BigInt, Double, OneByteString, TwoByteString, FourByteString.
}
// Now resolve the super interfaces.
ResolveInterfaces(interface_class, visited);

View file

@ -12,13 +12,11 @@ namespace dart {
class Class;
class Function;
class RawClass;
class RawType;
class Script;
class String;
class Type;
class TypeArguments;
class UnresolvedClass;
// Traverses all pending, unfinalized classes, validates and marks them as
// finalized.
@ -38,26 +36,17 @@ class ClassFinalizer : public AllStatic {
// Set the error message on failure (to String::null() if no error).
static RawType* FinalizeAndCanonicalizeType(const Type& type, String* errmsg);
// Notify finalizer to expect classes to be finalized.
static void ExpectClassesToFinalize();
// Pending classes are classes that need to be finalized.
static void AddPendingClasses(const GrowableArray<const Class*>& classes);
// Return true after a call to ExpectClassesToFinalize() and before a call to
// FinalizeAllClasses().
static bool IsExpectingClassesToFinalize();
// Add given classes to the list of pending classes to be finalized.
// ExpectClassesToFinalize() must be called prior to AddClassesToFinalize().
static void AddClassesToFinalize(const GrowableArray<const Class*>& classes);
// Return false if we still have classes pending to be finalized or expecting
// more classes to be finalized.
static bool AllClassesFinalized() { return !IsExpectingClassesToFinalize(); }
// Return false if we still have classes pending to be finalized.
static bool AllClassesFinalized();
// Return whether class finalization failed.
// The function returns true if the finalization was successful.
// If finalization fails, an error message is set in the sticky error field
// in the object store.
static bool FinalizeAllClasses();
static bool FinalizePendingClasses();
// Verify that the pending classes have been properly prefinalized. This is
// needed during bootstrapping where the classes have been preloaded.
@ -67,8 +56,6 @@ class ClassFinalizer : public AllStatic {
static void FinalizeClass(const Class& cls);
static bool IsSuperCycleFree(const Class& cls);
static void CheckForLegalConstClass(const Class& cls);
static RawClass* ResolveClass(const Class& cls,
const UnresolvedClass& unresolved_class);
static void ResolveSuperClass(const Class& cls);
static void ResolveDefaultClass(const Class& cls);
static void ResolveInterfaces(const Class& cls,
@ -77,7 +64,6 @@ class ClassFinalizer : public AllStatic {
const TypeArguments& arguments);
static RawType* ResolveType(const Class& cls, const Type& type);
static RawType* FinalizeType(const Type& type);
static void ResolveAndFinalizeUpperBounds(const Class& cls);
static void ResolveAndFinalizeSignature(const Class& cls,
const Function& function);
static void ResolveAndFinalizeMemberTypes(const Class& cls);

View file

@ -22,29 +22,27 @@ static RawClass* CreateTestClass(const char* name) {
TEST_CASE(ClassFinalizer) {
ClassFinalizer::ExpectClassesToFinalize();
GrowableArray<const Class*> classes_1;
classes_1.Add(&Class::ZoneHandle(CreateTestClass("BMW")));
classes_1.Add(&Class::ZoneHandle(CreateTestClass("Porsche")));
ClassFinalizer::AddClassesToFinalize(classes_1);
ClassFinalizer::AddPendingClasses(classes_1);
GrowableArray<const Class*> classes_2;
classes_2.Add(&Class::ZoneHandle(CreateTestClass("Ferrari")));
classes_2.Add(&Class::ZoneHandle(CreateTestClass("Fiat")));
classes_2.Add(&Class::ZoneHandle(CreateTestClass("Alfa")));
ClassFinalizer::AddClassesToFinalize(classes_2);
EXPECT(ClassFinalizer::FinalizeAllClasses());
ClassFinalizer::AddPendingClasses(classes_2);
EXPECT(ClassFinalizer::FinalizePendingClasses());
for (int i = 0; i < classes_1.length(); i++) {
EXPECT(classes_1[i]->is_finalized());
}
for (int i = 0; i < classes_2.length(); i++) {
EXPECT(classes_2[i]->is_finalized());
}
EXPECT(ClassFinalizer::FinalizeAllClasses());
EXPECT(ClassFinalizer::FinalizePendingClasses());
}
TEST_CASE(ClassFinalize_Cycles) {
ClassFinalizer::ExpectClassesToFinalize();
GrowableArray<const Class*> classes;
classes.Add(&Class::ZoneHandle(CreateTestClass("Jungfrau")));
classes.Add(&Class::ZoneHandle(CreateTestClass("Eiger")));
@ -53,8 +51,8 @@ TEST_CASE(ClassFinalize_Cycles) {
Type::Handle(Type::NewNonParameterizedType(*classes[1])));
classes[1]->set_super_type(
Type::Handle(Type::NewNonParameterizedType(*classes[0])));
ClassFinalizer::AddClassesToFinalize(classes);
EXPECT(!ClassFinalizer::FinalizeAllClasses());
ClassFinalizer::AddPendingClasses(classes);
EXPECT(!ClassFinalizer::FinalizePendingClasses());
}
@ -65,7 +63,6 @@ static RawLibrary* NewLib(const char* url_chars) {
TEST_CASE(ClassFinalize_Resolve) {
ClassFinalizer::ExpectClassesToFinalize();
GrowableArray<const Class*> classes;
Class& rhb = Class::ZoneHandle(CreateTestClass("RhB"));
Class& sbb = Class::ZoneHandle(CreateTestClass("SBB"));
@ -80,8 +77,8 @@ TEST_CASE(ClassFinalize_Resolve) {
TypeArguments& type_arguments = TypeArguments::Handle();
rhb.set_super_type(Type::Handle(Type::NewParameterizedType(
Object::Handle(unresolved.raw()), type_arguments)));
ClassFinalizer::AddClassesToFinalize(classes);
EXPECT(ClassFinalizer::FinalizeAllClasses());
ClassFinalizer::AddPendingClasses(classes);
EXPECT(ClassFinalizer::FinalizePendingClasses());
}
} // namespace dart

View file

@ -1389,10 +1389,11 @@ void CodeGenerator::GenerateInstanceOf(intptr_t node_id,
const Bool& bool_true = Bool::ZoneHandle(Bool::True());
const Bool& bool_false = Bool::ZoneHandle(Bool::False());
// All instances are of a subtype of the Object type.
// All instances are of type Object.
const Type& object_type =
Type::Handle(Isolate::Current()->object_store()->object_type());
if (type.IsInstantiated() && object_type.IsSubtypeOf(type)) {
// All objects are an instance of the Object class.
__ PushObject(negate_result ? bool_false : bool_true);
return;
}

View file

@ -331,7 +331,7 @@ CODEGEN_TEST_GENERATE(InstanceCallCodegen, test) {
Script& script = Script::Handle(Script::New(url, source, RawScript::kSource));
Library& lib = MakeTestLibrary("TestLib");
EXPECT(CompilerTest::TestCompileScript(lib, script));
EXPECT(ClassFinalizer::FinalizeAllClasses());
EXPECT(ClassFinalizer::FinalizePendingClasses());
Class& cls = Class::ZoneHandle(LookupClass(lib, "A"));
EXPECT(!cls.IsNull());
@ -467,7 +467,7 @@ CODEGEN_TEST_GENERATE(AllocateNewObjectCodegen, test) {
Script& script = Script::Handle(Script::New(url, source, RawScript::kSource));
Library& lib = MakeTestLibrary("TestLib");
EXPECT(CompilerTest::TestCompileScript(lib, script));
EXPECT(ClassFinalizer::FinalizeAllClasses());
EXPECT(ClassFinalizer::FinalizePendingClasses());
Class& cls = Class::ZoneHandle(LookupClass(lib, "A"));
EXPECT(!cls.IsNull());

View file

@ -52,7 +52,7 @@ TEST_CASE(CodeIndexTable) {
EXPECT(CompilerTest::TestCompileScript(lib, script));
clsA = lib.LookupClass(String::Handle(String::NewSymbol("A")));
EXPECT(!clsA.IsNull());
ClassFinalizer::FinalizeAllClasses();
ClassFinalizer::FinalizePendingClasses();
for (int i = 0; i < kNumFunctions; i++) {
OS::SNPrint(buffer, 256, "foo%d", i);
function_name = String::New(buffer);
@ -103,7 +103,7 @@ TEST_CASE(CodeIndexTable) {
EXPECT(CompilerTest::TestCompileScript(lib, script));
clsB = lib.LookupClass(String::Handle(String::NewSymbol("B")));
EXPECT(!clsB.IsNull());
ClassFinalizer::FinalizeAllClasses();
ClassFinalizer::FinalizePendingClasses();
for (int i = 0; i < kNumFunctions; i++) {
OS::SNPrint(buffer, 256, "moo%d", i);
function_name = String::New(buffer);

View file

@ -313,7 +313,7 @@ static void CompileAll(Dart_Handle* result) {
// Return error if isolate is in an inconsistent state.
// Return NULL when no error condition exists.
static const char* CheckIsolateState() {
if (!ClassFinalizer::FinalizeAllClasses()) {
if (!ClassFinalizer::FinalizePendingClasses()) {
// Make a copy of the error message as the original message string
// may get deallocated when we return back from the Dart API call.
const String& err =

View file

@ -239,7 +239,6 @@ void Object::InitOnce() {
// Allocate and initialize the null class.
cls = Class::New<Instance>();
cls.set_is_finalized();
null_class_ = cls.raw();
// Complete initialization of null_ instance, i.e. initialize its class_
@ -265,7 +264,6 @@ void Object::InitOnce() {
// see GetSingletonClassIndex) and its array fields cannot be set to the empty
// array, but remain null.
cls = Class::New<Instance>();
cls.set_is_finalized();
cls.set_is_interface();
dynamic_class_ = cls.raw();
@ -274,7 +272,6 @@ void Object::InitOnce() {
unresolved_class_class_ = cls.raw();
cls = Class::New<Instance>();
cls.set_is_finalized();
void_class_ = cls.raw();
cls = Class::New<ParameterizedType>();
@ -338,33 +335,13 @@ void Object::InitOnce() {
}
RawClass* Object::CreateAndRegisterCoreInterface(const char* cname,
const Script& script,
const Library& core_lib) {
const String& name = String::Handle(String::NewSymbol(cname));
const Class& cls = Class::Handle(Class::NewInterface(name, script));
core_lib.AddClass(cls);
return cls.raw();
}
void Object::RegisterCoreImplClass(const Class& cls,
const char* cname,
const Script& impl_script,
const Library& core_impl_lib) {
const String& name = String::Handle(String::NewSymbol(cname));
cls.set_name(name);
cls.set_script(impl_script);
core_impl_lib.AddClass(cls);
}
void Object::Init(Isolate* isolate) {
TIMERSCOPE(time_bootstrap);
ObjectStore* object_store = isolate->object_store();
Class& cls = Class::Handle();
Type& type = Type::Handle();
String& name = String::Handle();
Array& array = Array::Handle();
// All RawArray fields will be initialized to an empty array, therefore
@ -386,6 +363,52 @@ void Object::Init(Isolate* isolate) {
// has been created.
cls.InitEmptyFields();
cls = Class::New<ImmutableArray>();
object_store->set_immutable_array_class(cls);
cls.set_type_arguments_instance_field_offset(Array::type_arguments_offset());
// Allocate and initialize the object class and type.
cls = Class::New<Instance>();
object_store->set_object_class(cls);
type = Type::NewNonParameterizedType(cls);
object_store->set_object_type(type);
cls = Class::New<Smi>();
object_store->set_smi_class(cls);
cls = Class::New<Mint>();
object_store->set_mint_class(cls);
cls = Class::New<Bigint>();
object_store->set_bigint_class(cls);
cls = Class::New<Double>();
object_store->set_double_class(cls);
cls = Class::New<OneByteString>();
object_store->set_one_byte_string_class(cls);
cls = Class::New<TwoByteString>();
object_store->set_two_byte_string_class(cls);
cls = Class::New<FourByteString>();
object_store->set_four_byte_string_class(cls);
cls = Class::New<Bool>();
object_store->set_bool_class(cls);
cls = Class::New<UnhandledException>();
object_store->set_unhandled_exception_class(cls);
cls = Class::New<Stacktrace>();
object_store->set_stacktrace_class(cls);
// Set the super type so that the 'toString' method is implemented.
type = object_store->object_type();
cls.set_super_type(type);
cls = Class::New<JSRegExp>();
object_store->set_jsregexp_class(cls);
// Setup the symbol table used within the String class.
const int kInitialSymbolTableSize = 16;
array = Array::New(kInitialSymbolTableSize + 1);
@ -393,145 +416,156 @@ void Object::Init(Isolate* isolate) {
array.SetAt(kInitialSymbolTableSize, Smi::Handle(Smi::New(0)));
object_store->set_symbol_table(array);
// Pre-allocate the OneByteString class needed by the symbol table.
cls = Class::New<OneByteString>();
object_store->set_one_byte_string_class(cls);
// Basic infrastructure has been setup, initialize the class dictionary.
Library::InitCoreLibrary(isolate);
Library& core_lib = Library::Handle(Library::CoreLibrary());
Library& core_lib = Library::Handle(isolate->object_store()->core_library());
ASSERT(!core_lib.IsNull());
Library& core_impl_lib = Library::Handle(Library::CoreImplLibrary());
ASSERT(!core_impl_lib.IsNull());
object_store->set_pending_classes(Array::Handle());
// Allocate pre-initialized values.
Bool& bool_value = Bool::Handle();
bool_value = Bool::New(true);
object_store->set_true_value(bool_value);
bool_value = Bool::New(false);
object_store->set_false_value(bool_value);
object_store->set_pending_classes(Array::Handle(Array::Empty()));
Context& context = Context::Handle(Context::New(0));
object_store->set_empty_context(context);
// Now that the symbol table is initialized and that the core dictionary as
// well as the core implementation dictionary have been setup, preallocate
// remaining classes and register them by name in the dictionaries.
// Now that the String class is initialized and the dictionary has been setup,
// add the names to preallocated classes and register them in the dictionary.
const Script& impl_script = Script::Handle(Bootstrap::LoadImplScript());
GrowableArray<const Class*> pending_classes;
cls = Class::New<Smi>();
object_store->set_smi_class(cls);
RegisterCoreImplClass(cls, "Smi", impl_script, core_impl_lib);
pending_classes.Add(&Class::ZoneHandle(cls.raw()));
name = String::NewSymbol("Smi");
cls = object_store->smi_class();
cls.set_name(name);
cls.set_script(impl_script);
core_impl_lib.AddClass(cls);
cls = Class::New<Mint>();
object_store->set_mint_class(cls);
RegisterCoreImplClass(cls, "Mint", impl_script, core_impl_lib);
pending_classes.Add(&Class::ZoneHandle(cls.raw()));
name = String::NewSymbol("OneByteString");
cls = object_store->one_byte_string_class();
cls.set_name(name);
cls.set_script(impl_script);
core_impl_lib.AddClass(cls);
cls = Class::New<Bigint>();
object_store->set_bigint_class(cls);
RegisterCoreImplClass(cls, "Bigint", impl_script, core_impl_lib);
pending_classes.Add(&Class::ZoneHandle(cls.raw()));
name = String::NewSymbol("TwoByteString");
cls = object_store->two_byte_string_class();
cls.set_name(name);
cls.set_script(impl_script);
core_impl_lib.AddClass(cls);
cls = Class::New<Double>();
object_store->set_double_class(cls);
RegisterCoreImplClass(cls, "Double", impl_script, core_impl_lib);
pending_classes.Add(&Class::ZoneHandle(cls.raw()));
name = String::NewSymbol("FourByteString");
cls = object_store->four_byte_string_class();
cls.set_name(name);
cls.set_script(impl_script);
core_impl_lib.AddClass(cls);
cls = Class::New<Bool>();
object_store->set_bool_class(cls);
RegisterCoreImplClass(cls, "Bool", impl_script, core_impl_lib);
pending_classes.Add(&Class::ZoneHandle(cls.raw()));
name = String::NewSymbol("Mint");
cls = object_store->mint_class();
cls.set_name(name);
cls.set_script(impl_script);
core_impl_lib.AddClass(cls);
cls = object_store->array_class(); // Was allocated above.
RegisterCoreImplClass(cls, "ObjectArray", impl_script, core_impl_lib);
pending_classes.Add(&Class::ZoneHandle(cls.raw()));
name = String::NewSymbol("Bigint");
cls = object_store->bigint_class();
cls.set_name(name);
cls.set_script(impl_script);
core_impl_lib.AddClass(cls);
cls = Class::New<ImmutableArray>();
object_store->set_immutable_array_class(cls);
cls.set_type_arguments_instance_field_offset(Array::type_arguments_offset());
name = String::NewSymbol("Double");
cls = object_store->double_class();
cls.set_name(name);
cls.set_script(impl_script);
core_impl_lib.AddClass(cls);
name = String::NewSymbol("Bool");
cls = object_store->bool_class();
cls.set_name(name);
cls.set_script(impl_script);
core_impl_lib.AddClass(cls);
name = String::NewSymbol("ObjectArray");
cls = object_store->array_class();
cls.set_name(name);
cls.set_script(impl_script);
core_impl_lib.AddClass(cls);
name = String::NewSymbol("ImmutableArray");
cls = object_store->immutable_array_class();
ASSERT(object_store->immutable_array_class() != object_store->array_class());
RegisterCoreImplClass(cls, "ImmutableArray", impl_script, core_impl_lib);
pending_classes.Add(&Class::ZoneHandle(cls.raw()));
cls.set_name(name);
cls.set_script(impl_script);
core_impl_lib.AddClass(cls);
cls = object_store->one_byte_string_class(); // Was allocated above.
RegisterCoreImplClass(cls, "OneByteString", impl_script, core_impl_lib);
pending_classes.Add(&Class::ZoneHandle(cls.raw()));
name = String::NewSymbol("UnhandledException");
cls = object_store->unhandled_exception_class();
cls.set_name(name);
cls.set_script(impl_script);
core_impl_lib.AddClass(cls);
cls = Class::New<TwoByteString>();
object_store->set_two_byte_string_class(cls);
RegisterCoreImplClass(cls, "TwoByteString", impl_script, core_impl_lib);
pending_classes.Add(&Class::ZoneHandle(cls.raw()));
name = String::NewSymbol("Stacktrace");
cls = object_store->stacktrace_class();
cls.set_name(name);
cls.set_script(impl_script);
core_impl_lib.AddClass(cls);
cls = Class::New<FourByteString>();
object_store->set_four_byte_string_class(cls);
RegisterCoreImplClass(cls, "FourByteString", impl_script, core_impl_lib);
pending_classes.Add(&Class::ZoneHandle(cls.raw()));
cls = Class::New<UnhandledException>();
object_store->set_unhandled_exception_class(cls);
RegisterCoreImplClass(cls, "UnhandledException", impl_script, core_impl_lib);
pending_classes.Add(&Class::ZoneHandle(cls.raw()));
cls = Class::New<Stacktrace>();
object_store->set_stacktrace_class(cls);
RegisterCoreImplClass(cls, "Stacktrace", impl_script, core_impl_lib);
pending_classes.Add(&Class::ZoneHandle(cls.raw()));
// Super type set below, after Object is allocated.
cls = Class::New<JSRegExp>();
object_store->set_jsregexp_class(cls);
RegisterCoreImplClass(cls, "JSSyntaxRegExp", impl_script, core_impl_lib);
pending_classes.Add(&Class::ZoneHandle(cls.raw()));
name = String::NewSymbol("JSSyntaxRegExp");
cls = object_store->jsregexp_class();
cls.set_name(name);
cls.set_script(impl_script);
core_impl_lib.AddClass(cls);
// Initialize the base interfaces used by the core VM classes.
const Script& script = Script::Handle(Bootstrap::LoadScript());
// Allocate and initialize the Object class and type.
// Object class is the only pre-allocated non-interface in the core library.
cls = Class::New<Instance>();
object_store->set_object_class(cls);
cls.set_name(String::Handle(String::NewSymbol("Object")));
name = String::NewSymbol("Object");
cls = object_store->object_class();
cls.set_name(name);
cls.set_script(script);
core_lib.AddClass(cls);
pending_classes.Add(&Class::ZoneHandle(cls.raw()));
type = Type::NewNonParameterizedType(cls);
object_store->set_object_type(type);
// Set the super type of class Stacktrace to Object type so that the
// 'toString' method is implemented.
cls = object_store->stacktrace_class();
cls.set_super_type(type);
cls = CreateAndRegisterCoreInterface("Function", script, core_lib);
pending_classes.Add(&Class::ZoneHandle(cls.raw()));
name = String::NewSymbol("Function");
cls = Class::NewInterface(name, script);
core_lib.AddClass(cls);
type = Type::NewNonParameterizedType(cls);
object_store->set_function_interface(type);
cls = CreateAndRegisterCoreInterface("num", script, core_lib);
pending_classes.Add(&Class::ZoneHandle(cls.raw()));
name = String::NewSymbol("num");
cls = Class::NewInterface(name, script);
core_lib.AddClass(cls);
type = Type::NewNonParameterizedType(cls);
object_store->set_number_interface(type);
cls = CreateAndRegisterCoreInterface("int", script, core_lib);
pending_classes.Add(&Class::ZoneHandle(cls.raw()));
name = String::NewSymbol("int");
cls = Class::NewInterface(name, script);
core_lib.AddClass(cls);
type = Type::NewNonParameterizedType(cls);
object_store->set_int_interface(type);
cls = CreateAndRegisterCoreInterface("double", script, core_lib);
pending_classes.Add(&Class::ZoneHandle(cls.raw()));
name = String::NewSymbol("double");
cls = Class::NewInterface(name, script);
core_lib.AddClass(cls);
type = Type::NewNonParameterizedType(cls);
object_store->set_double_interface(type);
cls = CreateAndRegisterCoreInterface("String", script, core_lib);
pending_classes.Add(&Class::ZoneHandle(cls.raw()));
name = String::NewSymbol("String");
cls = Class::NewInterface(name, script);
core_lib.AddClass(cls);
type = Type::NewNonParameterizedType(cls);
object_store->set_string_interface(type);
cls = CreateAndRegisterCoreInterface("bool", script, core_lib);
pending_classes.Add(&Class::ZoneHandle(cls.raw()));
name = String::NewSymbol("bool");
cls = Class::NewInterface(name, script);
core_lib.AddClass(cls);
type = Type::NewNonParameterizedType(cls);
object_store->set_bool_interface(type);
cls = CreateAndRegisterCoreInterface("List", script, core_lib);
pending_classes.Add(&Class::ZoneHandle(cls.raw()));
name = String::NewSymbol("List");
cls = Class::NewInterface(name, script);
core_lib.AddClass(cls);
type = Type::NewNonParameterizedType(cls);
object_store->set_list_interface(type);
@ -556,21 +590,10 @@ void Object::Init(Isolate* isolate) {
object_store->set_dynamic_type(type);
core_lib.AddClass(cls);
// Add the preallocated classes to the list of classes to be finalized.
ClassFinalizer::ExpectClassesToFinalize();
ClassFinalizer::AddClassesToFinalize(pending_classes);
// Allocate pre-initialized values.
Bool& bool_value = Bool::Handle();
bool_value = Bool::New(true);
object_store->set_true_value(bool_value);
bool_value = Bool::New(false);
object_store->set_false_value(bool_value);
// Finish the initialization by compiling the bootstrap scripts containing the
// base interfaces and the implementation of the internal classes.
Bootstrap::Compile(core_lib, script);
Bootstrap::Compile(core_impl_lib, impl_script);
// Finish the initialization by compiling the bootstrap script containing the
// implementation of the internal classes.
Bootstrap::Compile(Library::Handle(Library::CoreLibrary()), script);
Bootstrap::Compile(Library::Handle(Library::CoreImplLibrary()), impl_script);
Bootstrap::SetupNativeResolver();
@ -1035,25 +1058,17 @@ RawClass* Class::NewSignatureClass(const String& name,
result.set_type_parameter_extends(type_parameter_extends);
result.SetFields(Array::Handle(Array::Empty()));
result.SetFunctions(Array::Handle(Array::Empty()));
// Implements interface "Function".
// Implements interface Function.
const Type& function_interface = Type::Handle(Type::FunctionInterface());
const Array& interfaces = Array::Handle(Array::New(1, Heap::kOld));
interfaces.SetAt(0, function_interface);
result.set_interfaces(interfaces);
// Unless the signature function already has a signature class, create a
// canonical signature class by having the signature function point back to
// canonical signature class by having the signature function pointing back to
// the signature class.
if (signature_function.signature_class() == Object::null()) {
signature_function.set_signature_class(result);
}
// If the class finalizer is expecting more pending classes to finalize, it
// will add the signature class to the pending list in order to postpone
// finalization of the signature type.
const Type& signature_type = Type::Handle(result.SignatureType());
ASSERT(!signature_type.IsFinalized());
String& errmsg = String::Handle();
ClassFinalizer::FinalizeAndCanonicalizeType(signature_type, &errmsg);
ASSERT(errmsg.IsNull());
return result.raw();
}
@ -1321,8 +1336,6 @@ bool Class::TestType(TypeTestKind test,
const TypeArguments& type_arguments,
const Class& other,
const TypeArguments& other_type_arguments) const {
ASSERT(is_finalized());
ASSERT(other.is_finalized());
if (test == kIsAssignableTo) {
// The spec states that "a type T is assignable to a type S if T is a
// subtype of S or S is a subtype of T". This is from the perspective of a
@ -1797,12 +1810,6 @@ bool Type::IsListInterface() const {
}
bool Type::IsSignatureType() const {
return HasResolvedTypeClass() &&
Class::Handle(type_class()).IsSignatureClass();
}
bool Type::IsMoreSpecificThan(const Type& other) const {
ASSERT(IsFinalized());
ASSERT(other.IsFinalized());
@ -2007,7 +2014,6 @@ RawType* ParameterizedType::InstantiateFrom(
offset);
}
const Class& cls = Class::Handle(type_class());
ASSERT(cls.is_finalized());
ParameterizedType& instantiated_type = ParameterizedType::Handle(
ParameterizedType::New(cls, type_arguments));
ASSERT(type_arguments.IsNull() ||

View file

@ -245,14 +245,6 @@ CLASS_LIST_NO_OBJECT(DEFINE_CLASS_TESTER);
static RawClass* GetSingletonClass(int index);
static const char* GetSingletonClassName(int index);
static RawClass* CreateAndRegisterCoreInterface(const char* cname,
const Script& script,
const Library& core_lib);
static void RegisterCoreImplClass(const Class& cls,
const char* cname,
const Script& impl_script,
const Library& core_impl_lib);
static void Init(Isolate* isolate);
static void InitFromSnapshot(Isolate* isolate);
static void InitOnce();
@ -749,9 +741,6 @@ class Type : public Object {
// Check if this type represents the 'List' interface.
bool IsListInterface() const;
// Check if this type represents a signature type.
bool IsSignatureType() const;
// Check if this type is an interface type.
bool IsInterfaceType() const {
if (!HasResolvedTypeClass()) {

View file

@ -204,6 +204,7 @@ class ObjectStore {
RawArray* pending_classes() const { return pending_classes_; }
void set_pending_classes(const Array& value) {
ASSERT(!value.IsNull());
pending_classes_ = value.raw();
}

View file

@ -5,7 +5,6 @@
#include "vm/assert.h"
#include "vm/assembler.h"
#include "vm/bigint_operations.h"
#include "vm/class_finalizer.h"
#include "vm/isolate.h"
#include "vm/object.h"
#include "vm/object_store.h"
@ -1745,8 +1744,6 @@ TEST_CASE(Closure) {
Function& function = Function::Handle();
const String& function_name = String::Handle(String::NewSymbol("foo"));
function = Function::NewClosureFunction(function_name, parent, 0);
// Postpone signature class finalization.
ClassFinalizer::ExpectClassesToFinalize();
const Class& signature_class = Class::Handle(
Class::NewSignatureClass(function_name, function, script));
const Closure& closure = Closure::Handle(Closure::New(function, context));

View file

@ -174,8 +174,6 @@ Parser::Parser(const Script& script, const Library& library)
current_class_(Class::Handle()),
library_(library),
try_blocks_list_(NULL) {
ASSERT(!tokens_.IsNull());
ASSERT(!library.IsNull());
SetPosition(0);
}
@ -194,8 +192,6 @@ Parser::Parser(const Script& script,
current_class_(Class::Handle(current_function_.owner())),
library_(Library::Handle(current_class_.library())),
try_blocks_list_(NULL) {
ASSERT(!tokens_.IsNull());
ASSERT(!function.IsNull());
SetPosition(token_index);
}
@ -2616,8 +2612,7 @@ void Parser::ParseFunctionTypeAlias(GrowableArray<const Class*>* classes) {
// Allocate an interface to hold the type parameters and their 'extends'
// constraints. Make it the owner of the function type descriptor.
const Class& alias_owner = Class::Handle(
Class::New(String::Handle(String::NewSymbol(":alias_owner")),
Script::Handle()));
Class::New(String::Handle(String::NewSymbol("")), Script::Handle()));
alias_owner.set_is_interface();
set_current_class(alias_owner);
ParseTypeParameters(alias_owner);
@ -3212,14 +3207,9 @@ void Parser::ParseTopLevel() {
is_top_level_ = true;
TopLevel top_level;
Class& toplevel_class = Class::ZoneHandle(
Class::New(String::ZoneHandle(String::NewSymbol("::")), script_));
Class::New(String::ZoneHandle(String::NewSymbol("")), script_));
toplevel_class.set_library(library_);
// We notify the class finalizer to expect classes to finalize.
// This allows signature classes generated at runtime to be properly
// finalized, without finalizing them prematurely at compile time.
ClassFinalizer::ExpectClassesToFinalize();
if (is_library_source()) {
ParseLibraryDefinition();
}
@ -3255,7 +3245,7 @@ void Parser::ParseTopLevel() {
library_.AddAnonymousClass(toplevel_class);
classes.Add(&toplevel_class);
}
ClassFinalizer::AddClassesToFinalize(classes);
ClassFinalizer::AddPendingClasses(classes);
}
@ -3689,8 +3679,8 @@ AstNode* Parser::ParseFunctionStatement(bool is_literal) {
if (!errmsg.IsNull()) {
ErrorMsg(errmsg.ToCString());
}
// The call to ClassFinalizer::FinalizeAndCanonicalizeType may have
// extended the vector of type arguments.
// The call to ClassFinalizer::FinalizeTypeWhileParsing may have extended
// the vector of type arguments.
ASSERT(signature_type_arguments.IsNull() ||
(signature_type_arguments.Length() ==
signature_class.NumTypeArguments()));

View file

@ -120,7 +120,7 @@ TEST_CASE(ParseClassDefinition) {
script.Tokenize(String::Handle(String::New("")));
Parser::ParseCompilationUnit(lib, script);
EXPECT(ClassFinalizer::FinalizeAllClasses());
EXPECT(ClassFinalizer::FinalizePendingClasses());
CheckField(lib, "A", "f1", false, false);
CheckField(lib, "A", "f2", false, true);
CheckField(lib, "A", "f3", false, true);
@ -164,7 +164,7 @@ TEST_CASE(Parser_TopLevel) {
script.Tokenize(String::Handle(String::New("")));
Parser::ParseCompilationUnit(lib, script);
EXPECT(ClassFinalizer::FinalizeAllClasses());
EXPECT(ClassFinalizer::FinalizePendingClasses());
DumpFunction(lib, "A", "foo");
DumpFunction(lib, "A", "bar");

View file

@ -45,7 +45,7 @@ static void SetupFunction(const char* test_library_name,
Library& lib = Library::Handle(Library::New(lib_name));
lib.Register();
EXPECT(CompilerTest::TestCompileScript(lib, script));
EXPECT(ClassFinalizer::FinalizeAllClasses());
EXPECT(ClassFinalizer::FinalizePendingClasses());
}

View file

@ -400,7 +400,7 @@ UNIT_TEST_CASE(FullSnapshot1) {
// Create a test library and Load up a test script in it.
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
ClassFinalizer::FinalizeAllClasses();
ClassFinalizer::FinalizePendingClasses();
timer1.Stop();
OS::PrintErr("Without Snapshot: %dus\n", timer1.TotalElapsedTime());