Skip to content

Commit

Permalink
Detect circular dependencies in compile time constants
Browse files Browse the repository at this point in the history
  • Loading branch information
mhausner committed Aug 21, 2013
1 parent eeb86b7 commit 6b20c0e
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 3 deletions.
4 changes: 4 additions & 0 deletions runtime/vm/object_store.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ ObjectStore::ObjectStore()
utf_library_(Library::null()),
libraries_(GrowableObjectArray::null()),
pending_classes_(GrowableObjectArray::null()),
pending_functions_(GrowableObjectArray::null()),
sticky_error_(Error::null()),
unhandled_exception_handler_(String::null()),
empty_context_(Context::null()),
Expand Down Expand Up @@ -105,6 +106,9 @@ bool ObjectStore::PreallocateObjects() {
ASSERT(this->out_of_memory() == Instance::null());
ASSERT(this->preallocated_stack_trace() == Stacktrace::null());

ASSERT(this->pending_functions() == GrowableObjectArray::null());
this->pending_functions_ = GrowableObjectArray::New();

Object& result = Object::Handle();
const Library& library = Library::Handle(Library::CoreLibrary());

Expand Down
5 changes: 5 additions & 0 deletions runtime/vm/object_store.h
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,10 @@ class ObjectStore {
pending_classes_ = value.raw();
}

RawGrowableObjectArray* pending_functions() const {
return pending_functions_;
}

RawError* sticky_error() const { return sticky_error_; }
void set_sticky_error(const Error& value) {
ASSERT(!value.IsNull());
Expand Down Expand Up @@ -485,6 +489,7 @@ class ObjectStore {
RawLibrary* utf_library_;
RawGrowableObjectArray* libraries_;
RawGrowableObjectArray* pending_classes_;
RawGrowableObjectArray* pending_functions_;
RawError* sticky_error_;
RawString* unhandled_exception_handler_;
RawContext* empty_context_;
Expand Down
38 changes: 36 additions & 2 deletions runtime/vm/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,8 @@ Parser::Parser(const Script& script, const Library& library, intptr_t token_pos)
current_class_(Class::Handle(isolate_)),
library_(Library::Handle(isolate_, library.raw())),
try_blocks_list_(NULL),
last_used_try_index_(CatchClauseNode::kInvalidTryIndex) {
last_used_try_index_(CatchClauseNode::kInvalidTryIndex),
unregister_pending_function_(false) {
ASSERT(tokens_iterator_.IsValid());
ASSERT(!library.IsNull());
}
Expand Down Expand Up @@ -284,7 +285,8 @@ Parser::Parser(const Script& script,
isolate_,
parsed_function->function().origin()).library())),
try_blocks_list_(NULL),
last_used_try_index_(CatchClauseNode::kInvalidTryIndex) {
last_used_try_index_(CatchClauseNode::kInvalidTryIndex),
unregister_pending_function_(false) {
ASSERT(tokens_iterator_.IsValid());
ASSERT(!current_function().IsNull());
if (FLAG_enable_type_checks) {
Expand All @@ -293,6 +295,19 @@ Parser::Parser(const Script& script,
}


Parser::~Parser() {
if (unregister_pending_function_) {
const GrowableObjectArray& pending_functions =
GrowableObjectArray::Handle(
isolate()->object_store()->pending_functions());
ASSERT(pending_functions.Length() > 0);
ASSERT(pending_functions.At(pending_functions.Length()-1) ==
current_function().raw());
pending_functions.RemoveLast();
}
}


void Parser::SetScript(const Script & script, intptr_t token_pos) {
script_ = script.raw();
tokens_iterator_.SetStream(TokenStream::Handle(script.tokens()), token_pos);
Expand Down Expand Up @@ -2360,6 +2375,23 @@ static void SetInvisible(LocalScope* scope, int num_variables, bool invisible) {
}


void Parser::CheckRecursiveInvocation() {
const GrowableObjectArray& pending_functions =
GrowableObjectArray::Handle(
isolate()->object_store()->pending_functions());
for (int i = 0; i < pending_functions.Length(); i++) {
if (pending_functions.At(i) == current_function().raw()) {
const String& fname =
String::Handle(current_function().UserVisibleName());
ErrorMsg("circular dependency for function %s", fname.ToCString());
}
}
ASSERT(!unregister_pending_function_);
pending_functions.Add(current_function());
unregister_pending_function_ = true;
}


// Parser is at the opening parenthesis of the formal parameter declaration
// of function. Parse the formal parameters, initializers and code.
SequenceNode* Parser::ParseConstructor(const Function& func,
Expand All @@ -2372,6 +2404,8 @@ SequenceNode* Parser::ParseConstructor(const Function& func,
const Class& cls = Class::Handle(func.Owner());
ASSERT(!cls.IsNull());

CheckRecursiveInvocation();

if (func.IsImplicitConstructor()) {
// Special case: implicit constructor.
// The parser adds an implicit default constructor when a class
Expand Down
5 changes: 5 additions & 0 deletions runtime/vm/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ class Parser : public ValueObject {

Parser(const Script& script, const Library& library, intptr_t token_pos);
Parser(const Script& script, ParsedFunction* function, intptr_t token_pos);
~Parser();

// The function for which we will generate code.
const Function& current_function() const;
Expand Down Expand Up @@ -320,6 +321,8 @@ class Parser : public ValueObject {
const Error& prev_error, intptr_t token_pos, const char* format, ...)
PRINTF_ATTRIBUTE(4, 5);

void CheckRecursiveInvocation();

const Instance& EvaluateConstExpr(AstNode* expr);
AstNode* RunStaticFieldInitializer(const Field& field);
RawObject* EvaluateConstConstructorCall(
Expand Down Expand Up @@ -693,6 +696,8 @@ class Parser : public ValueObject {
intptr_t AllocateTryIndex() { return ++last_used_try_index_; }
intptr_t last_used_try_index_;

bool unregister_pending_function_;

DISALLOW_COPY_AND_ASSIGN(Parser);
};

Expand Down
1 change: 0 additions & 1 deletion tests/co19/co19-runtime.status
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,6 @@ Language/07_Classes/6_Constructors/1_Generative_Constructors_A09_t01: fail # Dar
Language/12_Expressions/01_Constants_A01_t01: fail # co19 issue 522
Language/12_Expressions/01_Constants_A16_t01: fail # co19 issue 525
Language/12_Expressions/01_Constants_A16_t02: fail # co19 issue 525
Language/12_Expressions/01_Constants_A17_t03: crash # Dart issue 1681
Language/12_Expressions/03_Numbers_A01_t01: fail # co19 issue 522
Language/12_Expressions/03_Numbers_A01_t02: fail # co19 issue 522
Language/12_Expressions/03_Numbers_A01_t03: fail # co19 issue 522
Expand Down

0 comments on commit 6b20c0e

Please sign in to comment.