Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(879)

Unified Diff: runtime/vm/object.cc

Issue 14820028: Delay Class parsing until the class is actually used. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: runtime/vm/object.cc
===================================================================
--- runtime/vm/object.cc (revision 22914)
+++ runtime/vm/object.cc (working copy)
@@ -29,6 +29,7 @@
#include "vm/heap.h"
#include "vm/intermediate_language.h"
#include "vm/intrinsifier.h"
+#include "vm/longjump.h"
#include "vm/object_store.h"
#include "vm/parser.h"
#include "vm/runtime_entry.h"
@@ -363,6 +364,8 @@
cls.set_id(Class::kClassId);
cls.raw_ptr()->state_bits_ = 0;
cls.set_is_finalized();
+ cls.set_is_type_finalized();
+ cls.set_is_parsed();
cls.raw_ptr()->type_arguments_field_offset_in_words_ =
Class::kNoTypeArguments;
cls.raw_ptr()->num_native_fields_ = 0;
@@ -373,11 +376,15 @@
// Allocate and initialize the null class.
cls = Class::New<Instance>(kNullCid);
cls.set_is_finalized();
+ cls.set_is_type_finalized();
+ cls.set_is_parsed();
null_class_ = cls.raw();
// Allocate and initialize the free list element class.
cls = Class::New<FreeListElement::FakeInstance>(kFreeListElement);
cls.set_is_finalized();
+ cls.set_is_type_finalized();
+ cls.set_is_parsed();
// Allocate and initialize the sentinel values of Null class.
{
@@ -398,6 +405,8 @@
cls = Class::New<Instance>(kDynamicCid);
cls.set_is_finalized();
+ cls.set_is_type_finalized();
+ cls.set_is_parsed();
cls.set_is_abstract();
dynamic_class_ = cls.raw();
@@ -407,6 +416,8 @@
cls = Class::New<Instance>(kVoidCid);
cls.set_is_finalized();
+ cls.set_is_type_finalized();
+ cls.set_is_parsed();
void_class_ = cls.raw();
cls = Class::New<TypeArguments>();
@@ -994,6 +1005,7 @@
cls = Class::New<Instance>(kIllegalCid);
cls.set_is_prefinalized();
RegisterClass(cls, name, core_lib);
+ cls.set_is_prefinalized();
pending_classes.Add(cls, Heap::kOld);
type = Type::NewNonParameterizedType(cls);
object_store->set_string_type(type);
@@ -1543,7 +1555,7 @@
void Class::set_state_bits(intptr_t bits) const {
- raw_ptr()->state_bits_ = static_cast<uint8_t>(bits);
+ raw_ptr()->state_bits_ = static_cast<uint16_t>(bits);
}
@@ -1589,7 +1601,7 @@
bool Class::HasTypeArguments() const {
- if (!IsSignatureClass() && (is_finalized() || is_prefinalized())) {
+ if (!IsSignatureClass() && (is_type_finalized() || is_prefinalized())) {
// More efficient than calling NumTypeArguments().
return type_arguments_field_offset() != kNoTypeArguments;
} else {
@@ -1783,6 +1795,21 @@
}
+// Ensure that top level parsing of the class has been done.
+RawError* Class::EnsureIsParsed(Isolate* isolate) const {
+ if (!is_parsed()) {
+ ASSERT(isolate != NULL);
+ const Error& error = Error::Handle(isolate, Compiler::ParseClass(*this));
+ if (!error.IsNull() && (isolate->long_jump_base() != NULL)) {
+ isolate->long_jump_base()->Jump(1, error);
+ UNREACHABLE();
+ }
+ return error.raw();
+ }
+ return Error::null();
+}
+
+
void Class::SetFields(const Array& value) const {
ASSERT(!value.IsNull());
#if defined(DEBUG)
@@ -1848,6 +1875,7 @@
result.set_instance_size(Closure::InstanceSize());
result.set_next_field_offset(Closure::InstanceSize());
result.set_super_type(super_type);
+ result.set_is_parsed();
result.set_type_arguments_field_offset(Closure::type_arguments_offset());
// Implements interface "Function".
const Type& function_type = Type::Handle(Type::Function());
@@ -1908,6 +1936,8 @@
cls.set_next_field_offset(instance_size);
cls.set_num_native_fields(field_count);
cls.set_is_finalized();
+ cls.set_is_type_finalized();
+ cls.set_is_parsed();
library.AddClass(cls);
return cls.raw();
} else {
@@ -1994,6 +2024,26 @@
}
+void Class::set_is_type_finalized() const {
+ set_state_bits(TypeFinalizedBit::update(true, raw_ptr()->state_bits_));
+}
+
+
+void Class::set_is_patch() const {
+ set_state_bits(PatchBit::update(true, raw_ptr()->state_bits_));
+}
+
+
+void Class::set_is_parsed() const {
+ set_state_bits(ParsedBit::update(true, raw_ptr()->state_bits_));
+}
+
+
+void Class::set_is_synthesized_class() const {
+ set_state_bits(SynthesizedClassBit::update(true, raw_ptr()->state_bits_));
+}
+
+
void Class::set_is_const() const {
set_state_bits(ConstBit::update(true, raw_ptr()->state_bits_));
}
@@ -2027,6 +2077,18 @@
}
+void Class::add_patch_class(const Class& patch_class) const {
+ ASSERT(!patch_class.IsNull());
+ GrowableObjectArray& patch_classes = GrowableObjectArray::Handle();
+ patch_classes ^= raw_ptr()->patch_classes_;
+ if (patch_classes.IsNull()) {
+ patch_classes ^= GrowableObjectArray::New(1, Heap::kOld);
+ StorePointer(&raw_ptr()->patch_classes_, patch_classes.raw());
+ }
+ patch_classes.Add(patch_class);
+}
+
+
void Class::AddDirectSubclass(const Class& subclass) const {
ASSERT(!subclass.IsNull());
ASSERT(subclass.SuperClass() == raw());
@@ -2342,6 +2404,9 @@
RawFunction* Class::LookupFunction(const String& name) const {
Isolate* isolate = Isolate::Current();
+ if (EnsureIsParsed(isolate) != Error::null()) {
hausner 2013/05/21 20:07:30 How do errors during parsing get propagated to the
siva 2013/05/23 00:54:31 The function EnsureIsParsed does a Longjump on err
+ return Function::null();
+ }
Array& funcs = Array::Handle(isolate, functions());
if (funcs.IsNull()) {
// This can occur, e.g., for Null classes.
@@ -2375,6 +2440,9 @@
RawFunction* Class::LookupFunctionAllowPrivate(const String& name) const {
Isolate* isolate = Isolate::Current();
+ if (EnsureIsParsed(isolate) != Error::null()) {
+ return Function::null();
+ }
Array& funcs = Array::Handle(isolate, functions());
if (funcs.IsNull()) {
// This can occur, e.g., for Null classes.
@@ -2409,6 +2477,9 @@
intptr_t prefix_length,
const String& name) const {
Isolate* isolate = Isolate::Current();
+ if (EnsureIsParsed(isolate) != Error::null()) {
+ return Function::null();
+ }
Array& funcs = Array::Handle(isolate, functions());
Function& function = Function::Handle(isolate, Function::null());
String& function_name = String::Handle(isolate, String::null());
@@ -2429,12 +2500,16 @@
RawFunction* Class::LookupFunctionAtToken(intptr_t token_pos) const {
// TODO(hausner): we can shortcut the negative case if we knew the
// beginning and end token position of the class.
- Function& func = Function::Handle();
+ Isolate* isolate = Isolate::Current();
+ if (EnsureIsParsed(isolate) != Error::null()) {
+ return Function::null();
+ }
+ Function& func = Function::Handle(isolate);
func = LookupClosureFunction(token_pos);
if (!func.IsNull()) {
return func.raw();
}
- Array& funcs = Array::Handle(functions());
+ Array& funcs = Array::Handle(isolate, functions());
intptr_t len = funcs.Length();
for (intptr_t i = 0; i < len; i++) {
func ^= funcs.At(i);
@@ -2449,8 +2524,12 @@
RawField* Class::LookupInstanceField(const String& name) const {
+ Isolate* isolate = Isolate::Current();
+ if (EnsureIsParsed(isolate) != Error::null()) {
+ return Field::null();
+ }
ASSERT(is_finalized());
- const Field& field = Field::Handle(LookupField(name));
+ const Field& field = Field::Handle(isolate, LookupField(name));
if (!field.IsNull()) {
if (field.is_static()) {
// Name matches but it is not of the correct kind, return NULL.
@@ -2464,8 +2543,12 @@
RawField* Class::LookupStaticField(const String& name) const {
+ Isolate* isolate = Isolate::Current();
+ if (EnsureIsParsed(isolate) != Error::null()) {
+ return Field::null();
+ }
ASSERT(is_finalized());
- const Field& field = Field::Handle(LookupField(name));
+ const Field& field = Field::Handle(isolate, LookupField(name));
if (!field.IsNull()) {
if (!field.is_static()) {
// Name matches but it is not of the correct kind, return NULL.
@@ -2480,6 +2563,9 @@
RawField* Class::LookupField(const String& name) const {
Isolate* isolate = Isolate::Current();
+ if (EnsureIsParsed(isolate) != Error::null()) {
+ return Field::null();
+ }
const Array& flds = Array::Handle(isolate, fields());
Field& field = Field::Handle(isolate, Field::null());
String& field_name = String::Handle(isolate, String::null());
@@ -6896,6 +6982,10 @@
ClassDictionaryIterator it(lib);
while (it.HasNext()) {
cls = it.GetNextClass();
+ error = cls.EnsureIsParsed(Isolate::Current());
+ if (!error.IsNull()) {
+ return error.raw();
+ }
error = Compiler::CompileAllFunctions(cls);
if (!error.IsNull()) {
return error.raw();
@@ -9180,7 +9270,11 @@
RawInstance* Instance::New(const Class& cls, Heap::Space space) {
- Instance& result = Instance::Handle();
+ Isolate* isolate = Isolate::Current();
+ if (cls.EnsureIsParsed(isolate) != Error::null()) {
+ return Instance::null();
+ }
+ Instance& result = Instance::Handle(isolate);
{
intptr_t instance_size = cls.instance_size();
ASSERT(instance_size > 0);
@@ -9384,7 +9478,7 @@
} else {
// The actual type argument vector can be longer than necessary, because
// of type optimizations.
- if (IsFinalized() && cls.is_finalized()) {
+ if (IsFinalized() && cls.is_type_finalized()) {
first_type_param_index = cls.NumTypeArguments() - num_type_params;
} else {
first_type_param_index = num_args - num_type_params;

Powered by Google App Engine
This is Rietveld 408576698