Version 1.3.0-dev.7.5
svn merge -c 34481 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 34484 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 34486 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
Use changes to trunk/dart/tests/language/language.status from https://codereview.chromium.org/216383004
cd trunk/dart
svn revert tests/language/language.status
wget -O diff https://codereview.chromium.org/download/issue216383004_1_10018.diff
patch -p0 < diff
rm diff
R=kasperl@google.com
Review URL: https://codereview.chromium.org//216633003
git-svn-id: http://dart.googlecode.com/svn/trunk@34497 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/runtime/lib/corelib_sources.gypi b/runtime/lib/corelib_sources.gypi
index 1b94b04..f5f68cf 100644
--- a/runtime/lib/corelib_sources.gypi
+++ b/runtime/lib/corelib_sources.gypi
@@ -34,6 +34,7 @@
'integers_patch.dart',
'invocation_mirror.h',
'invocation_mirror_patch.dart',
+ 'lib_prefix.dart',
'map_patch.dart',
'null_patch.dart',
'object.cc',
diff --git a/runtime/lib/lib_prefix.dart b/runtime/lib/lib_prefix.dart
new file mode 100644
index 0000000..b1cac38
--- /dev/null
+++ b/runtime/lib/lib_prefix.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2014, 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.
+
+import "dart:async";
+import "dart:isolate";
+
+// This type corresponds to the VM-internal class LibraryPrefix.
+
+class _LibraryPrefix {
+ _load() native "LibraryPrefix_load";
+
+ loadLibrary() {
+ var completer = new Completer<bool>();
+ var port = new RawReceivePort();
+ port.handler = (_) {
+ this._load();
+ completer.complete(true);
+ port.close();
+ };
+ port.sendPort.send(1);
+ return completer.future;
+ }
+}
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index 1162ab4..6da79b2 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -230,4 +230,12 @@
return type.UserVisibleName();
}
+
+DEFINE_NATIVE_ENTRY(LibraryPrefix_load, 1) {
+ const LibraryPrefix& prefix =
+ LibraryPrefix::CheckedHandle(arguments->NativeArgAt(0));
+ prefix.LoadLibrary();
+ return Bool::Get(true).raw();
+}
+
} // namespace dart
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 6a2bafd..e6038e0 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -347,6 +347,8 @@
V(WeakProperty_getValue, 1) \
V(WeakProperty_setValue, 2) \
V(Uri_isWindowsPlatform, 0) \
+ V(LibraryPrefix_load, 1) \
+
class BootstrapNatives : public AllStatic {
public:
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 0d1e38e..8ffa3ce 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -579,6 +579,14 @@
function.SetCode(code);
ASSERT(CodePatcher::CodeIsPatchable(code));
}
+ if (parsed_function->HasDeferredPrefixes()) {
+ GrowableObjectArray* prefixes = parsed_function->DeferredPrefixes();
+ LibraryPrefix& prefix = LibraryPrefix::Handle();
+ for (intptr_t i = 0; i < prefixes->Length(); i++) {
+ prefix ^= prefixes->At(i);
+ prefix.RegisterDependentCode(code);
+ }
+ }
}
is_compiled = true;
done = true;
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 28f5fd7..7848d34 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -4492,7 +4492,7 @@
if (!library_prefix.IsNull()) {
library_prefix.AddImport(import_ns);
} else {
- library_prefix = LibraryPrefix::New(prefix_symbol, import_ns);
+ library_prefix = LibraryPrefix::New(prefix_symbol, import_ns, false);
library_vm.AddObject(library_prefix, prefix_symbol);
}
}
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 7fb08c8..771e6e8 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -125,7 +125,6 @@
RawClass* Object::token_stream_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::script_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::library_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
-RawClass* Object::library_prefix_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::namespace_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::code_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::instructions_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
@@ -569,9 +568,6 @@
cls = Class::New<Library>();
library_class_ = cls.raw();
- cls = Class::New<LibraryPrefix>();
- library_prefix_class_ = cls.raw();
-
cls = Class::New<Namespace>();
namespace_class_ = cls.raw();
@@ -770,7 +766,6 @@
SET_CLASS_NAME(token_stream, TokenStream);
SET_CLASS_NAME(script, Script);
SET_CLASS_NAME(library, LibraryClass);
- SET_CLASS_NAME(library_prefix, LibraryPrefix);
SET_CLASS_NAME(namespace, Namespace);
SET_CLASS_NAME(code, Code);
SET_CLASS_NAME(instructions, Instructions);
@@ -945,6 +940,9 @@
cls = Class::New<MixinAppType>();
object_store->set_mixin_app_type_class(cls);
+ cls = Class::New<LibraryPrefix>();
+ object_store->set_library_prefix_class(cls);
+
// Pre-allocate the OneByteString class needed by the symbol table.
cls = Class::NewStringClass(kOneByteStringCid);
object_store->set_one_byte_string_class(cls);
@@ -1063,6 +1061,11 @@
RegisterClass(cls, Symbols::Null(), core_lib);
pending_classes.Add(cls);
+ cls = object_store->library_prefix_class();
+ ASSERT(!cls.IsNull());
+ RegisterPrivateClass(cls, Symbols::_LibraryPrefix(), core_lib);
+ pending_classes.Add(cls);
+
cls = object_store->type_class();
RegisterPrivateClass(cls, Symbols::Type(), core_lib);
pending_classes.Add(cls);
@@ -1337,6 +1340,9 @@
cls = Class::New<Instance>(kInstanceCid);
object_store->set_object_class(cls);
+ cls = Class::New<LibraryPrefix>();
+ object_store->set_library_prefix_class(cls);
+
cls = Class::New<Type>();
object_store->set_type_class(cls);
@@ -2443,9 +2449,12 @@
function ^= code.function();
// If function uses dependent code switch it to unoptimized.
if (function.CurrentCode() == code.raw()) {
- ASSERT(function.HasOptimizedCode());
ReportSwitchingCode(code);
- function.SwitchToUnoptimizedCode();
+ if (code.is_optimized()) {
+ function.SwitchToUnoptimizedCode();
+ } else {
+ function.ClearCode();
+ }
}
}
}
@@ -9113,6 +9122,9 @@
void LibraryPrefix::AddImport(const Namespace& import) const {
intptr_t num_current_imports = num_imports();
+ // Prefixes with deferred libraries can only contain one library.
+ ASSERT((num_current_imports == 0) || !is_deferred_load());
+
// The library needs to be added to the list.
Array& imports = Array::Handle(this->imports());
const intptr_t length = (imports.IsNull()) ? 0 : imports.Length();
@@ -9128,6 +9140,9 @@
RawObject* LibraryPrefix::LookupObject(const String& name) const {
+ if (!is_loaded()) {
+ return Object::null();
+ }
Array& imports = Array::Handle(this->imports());
Object& obj = Object::Handle();
Namespace& import = Namespace::Handle();
@@ -9174,8 +9189,81 @@
}
+void LibraryPrefix::set_is_loaded() const {
+ raw_ptr()->is_loaded_ = true;
+}
+
+
+void LibraryPrefix::LoadLibrary() const {
+ // Non-deferred prefixes are loaded.
+ ASSERT(is_deferred_load() || is_loaded());
+ if (is_loaded()) {
+ return;
+ }
+ InvalidateDependentCode();
+ set_is_loaded();
+}
+
+
+RawArray* LibraryPrefix::dependent_code() const {
+ return raw_ptr()->dependent_code_;
+}
+
+
+void LibraryPrefix::set_dependent_code(const Array& array) const {
+ StorePointer(&raw_ptr()->dependent_code_, array.raw());
+}
+
+
+class PrefixDependentArray : public WeakCodeReferences {
+ public:
+ explicit PrefixDependentArray(const LibraryPrefix& prefix)
+ : WeakCodeReferences(Array::Handle(prefix.dependent_code())),
+ prefix_(prefix) {}
+
+ virtual void UpdateArrayTo(const Array& value) {
+ prefix_.set_dependent_code(value);
+ }
+
+ virtual void ReportDeoptimization(const Code& code) {
+ // This gets called when the code object is on the stack
+ // while nuking code that depends on a prefix. We don't expect
+ // this to happen, so make sure we die loudly if we find
+ // ourselves here.
+ UNIMPLEMENTED();
+ }
+
+ virtual void ReportSwitchingCode(const Code& code) {
+ if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
+ OS::PrintErr("Prefix '%s': deleting code for function '%s'\n",
+ String::Handle(prefix_.name()).ToCString(),
+ Function::Handle(code.function()).ToCString());
+ }
+ }
+
+ private:
+ const LibraryPrefix& prefix_;
+ DISALLOW_COPY_AND_ASSIGN(PrefixDependentArray);
+};
+
+
+void LibraryPrefix::RegisterDependentCode(const Code& code) const {
+ ASSERT(is_deferred_load());
+ ASSERT(!is_loaded());
+ PrefixDependentArray a(*this);
+ a.Register(code);
+}
+
+
+void LibraryPrefix::InvalidateDependentCode() const {
+ PrefixDependentArray a(*this);
+ a.DisableCode();
+}
+
+
RawLibraryPrefix* LibraryPrefix::New() {
- ASSERT(Object::library_prefix_class() != Class::null());
+ ASSERT(Isolate::Current()->object_store()->library_prefix_class() !=
+ Class::null());
RawObject* raw = Object::Allocate(LibraryPrefix::kClassId,
LibraryPrefix::InstanceSize(),
Heap::kOld);
@@ -9184,12 +9272,16 @@
RawLibraryPrefix* LibraryPrefix::New(const String& name,
- const Namespace& import) {
+ const Namespace& import,
+ bool deferred_load) {
const LibraryPrefix& result = LibraryPrefix::Handle(LibraryPrefix::New());
result.set_name(name);
result.set_num_imports(0);
+ result.raw_ptr()->is_deferred_load_ = deferred_load;
+ result.raw_ptr()->is_loaded_ = !deferred_load;
result.set_imports(Array::Handle(Array::New(kInitialSize)));
result.AddImport(import);
+ result.set_dependent_code(Object::null_array());
return result.raw();
}
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 0789c0e..9d6d35a 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -447,7 +447,6 @@
static RawClass* token_stream_class() { return token_stream_class_; }
static RawClass* script_class() { return script_class_; }
static RawClass* library_class() { return library_class_; }
- static RawClass* library_prefix_class() { return library_prefix_class_; }
static RawClass* namespace_class() { return namespace_class_; }
static RawClass* code_class() { return code_class_; }
static RawClass* instructions_class() { return instructions_class_; }
@@ -598,7 +597,6 @@
static RawClass* token_stream_class_; // Class of the TokenStream vm object.
static RawClass* script_class_; // Class of the Script vm object.
static RawClass* library_class_; // Class of the Library vm object.
- static RawClass* library_prefix_class_; // Class of Library prefix vm object.
static RawClass* namespace_class_; // Class of Namespace vm object.
static RawClass* code_class_; // Class of the Code vm object.
static RawClass* instructions_class_; // Class of the Instructions vm object.
@@ -2707,41 +2705,6 @@
};
-class LibraryPrefix : public Object {
- public:
- RawString* name() const { return raw_ptr()->name_; }
- virtual RawString* DictionaryName() const { return name(); }
-
- RawArray* imports() const { return raw_ptr()->imports_; }
- intptr_t num_imports() const { return raw_ptr()->num_imports_; }
-
- bool ContainsLibrary(const Library& library) const;
- RawLibrary* GetLibrary(int index) const;
- void AddImport(const Namespace& import) const;
- RawObject* LookupObject(const String& name) const;
- RawClass* LookupClass(const String& class_name) const;
-
- static intptr_t InstanceSize() {
- return RoundedAllocationSize(sizeof(RawLibraryPrefix));
- }
-
- static RawLibraryPrefix* New(const String& name, const Namespace& import);
-
- private:
- static const int kInitialSize = 2;
- static const int kIncrementSize = 2;
-
- void set_name(const String& value) const;
- void set_imports(const Array& value) const;
- void set_num_imports(intptr_t value) const;
-
- static RawLibraryPrefix* New();
-
- FINAL_HEAP_OBJECT_IMPLEMENTATION(LibraryPrefix, Object);
- friend class Class;
-};
-
-
// A Namespace contains the names in a library dictionary, filtered by
// the show/hide combinators.
class Namespace : public Object {
@@ -4106,6 +4069,58 @@
};
+class LibraryPrefix : public Instance {
+ public:
+ RawString* name() const { return raw_ptr()->name_; }
+ virtual RawString* DictionaryName() const { return name(); }
+
+ RawArray* imports() const { return raw_ptr()->imports_; }
+ intptr_t num_imports() const { return raw_ptr()->num_imports_; }
+
+ bool ContainsLibrary(const Library& library) const;
+ RawLibrary* GetLibrary(int index) const;
+ void AddImport(const Namespace& import) const;
+ RawObject* LookupObject(const String& name) const;
+ RawClass* LookupClass(const String& class_name) const;
+
+ bool is_deferred_load() const { return raw_ptr()->is_deferred_load_; }
+ bool is_loaded() const { return raw_ptr()->is_loaded_; }
+ void LoadLibrary() const;
+
+ // Return the list of code objects that were compiled when this
+ // prefix was not yet loaded. These code objects will be invalidated
+ // when the prefix is loaded.
+ RawArray* dependent_code() const;
+ void set_dependent_code(const Array& array) const;
+
+ // Add the given code object to the list of dependent ones.
+ void RegisterDependentCode(const Code& code) const;
+ void InvalidateDependentCode() const;
+
+ static intptr_t InstanceSize() {
+ return RoundedAllocationSize(sizeof(RawLibraryPrefix));
+ }
+
+ static RawLibraryPrefix* New(const String& name,
+ const Namespace& import,
+ bool deferred_load);
+
+ private:
+ static const int kInitialSize = 2;
+ static const int kIncrementSize = 2;
+
+ void set_name(const String& value) const;
+ void set_imports(const Array& value) const;
+ void set_num_imports(intptr_t value) const;
+ void set_is_loaded() const;
+
+ static RawLibraryPrefix* New();
+
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(LibraryPrefix, Instance);
+ friend class Class;
+};
+
+
// AbstractType is an abstract superclass.
// Subclasses of AbstractType are Type and TypeParameter.
class AbstractType : public Instance {
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index c8a046c..bc9e326 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -21,6 +21,7 @@
null_type_(Type::null()),
function_type_(Type::null()),
function_impl_type_(Type::null()),
+ library_prefix_class_(Class::null()),
type_class_(Class::null()),
number_type_(Type::null()),
int_type_(Type::null()),
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index b5f022a..3656235 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -69,6 +69,11 @@
function_impl_type_ = value.raw();
}
+ RawClass* library_prefix_class() const { return library_prefix_class_; }
+ void set_library_prefix_class(const Class& value) {
+ library_prefix_class_ = value.raw();
+ }
+
RawClass* type_class() const { return type_class_; }
void set_type_class(const Class& value) { type_class_ = value.raw(); }
@@ -431,6 +436,7 @@
RawType* null_type_;
RawType* function_type_;
RawType* function_impl_type_;
+ RawClass* library_prefix_class_;
RawClass* type_class_;
RawClass* type_ref_class_;
RawClass* type_parameter_class_;
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 797b523..88f4b3c 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -127,6 +127,22 @@
}
+void ParsedFunction::AddDeferredPrefix(const LibraryPrefix& prefix) {
+ ASSERT(prefix.is_deferred_load());
+ ASSERT(!prefix.is_loaded());
+ if (deferred_prefixes_ == NULL) {
+ deferred_prefixes_ =
+ &GrowableObjectArray::ZoneHandle(GrowableObjectArray::New());
+ }
+ for (intptr_t i = 0; i < deferred_prefixes_->Length(); i++) {
+ if (deferred_prefixes_->At(i) == prefix.raw()) {
+ return;
+ }
+ }
+ deferred_prefixes_->Add(prefix);
+}
+
+
void ParsedFunction::AllocateVariables() {
LocalScope* scope = node_sequence()->scope();
const intptr_t num_fixed_params = function().num_fixed_parameters();
@@ -4945,19 +4961,32 @@
if (url.Length() == 0) {
ErrorMsg("library url expected");
}
+ bool is_deferred_import = false;
+ if (is_import && (IsLiteral("deferred"))) {
+ is_deferred_import = true;
+ ConsumeToken();
+ CheckToken(Token::kAS, "'as' expected");
+ }
String& prefix = String::Handle();
+ intptr_t prefix_pos = 0;
if (is_import && (CurrentToken() == Token::kAS)) {
ConsumeToken();
+ prefix_pos = TokenPos();
prefix = ExpectIdentifier("prefix identifier expected")->raw();
}
Array& show_names = Array::Handle();
Array& hide_names = Array::Handle();
- if (IsLiteral("show") || IsLiteral("hide")) {
+ if (is_deferred_import || IsLiteral("show") || IsLiteral("hide")) {
GrowableObjectArray& show_list =
GrowableObjectArray::Handle(GrowableObjectArray::New());
GrowableObjectArray& hide_list =
GrowableObjectArray::Handle(GrowableObjectArray::New());
+ // Libraries imported through deferred import automatically hide
+ // the name 'loadLibrary'.
+ if (is_deferred_import) {
+ hide_list.Add(Symbols::LoadLibrary());
+ }
for (;;) {
if (IsLiteral("show")) {
ConsumeToken();
@@ -4985,6 +5014,7 @@
Library& library = Library::Handle(Library::LookupLibrary(canon_url));
if (library.IsNull()) {
// Call the library tag handler to load the library.
+ // TODO(hausner): do not load eagerly if import is deferred.
CallLibraryTagHandler(Dart_kImportTag, import_pos, canon_url);
// If the library tag handler succeded without registering the
// library we create an empty library to import.
@@ -5010,14 +5040,25 @@
ErrorMsg(import_pos, "private library is not accessible");
}
if (prefix.IsNull() || (prefix.Length() == 0)) {
+ ASSERT(!is_deferred_import);
library_.AddImport(ns);
} else {
LibraryPrefix& library_prefix = LibraryPrefix::Handle();
library_prefix = library_.LookupLocalLibraryPrefix(prefix);
if (!library_prefix.IsNull()) {
+ // Check that prefix names of deferred import clauses are
+ // unique.
+ if (!is_deferred_import && library_prefix.is_deferred_load()) {
+ ErrorMsg(prefix_pos,
+ "prefix '%s' already used in a deferred import clause",
+ prefix.ToCString());
+ }
+ if (is_deferred_import) {
+ ErrorMsg(prefix_pos, "prefix of deferred import must be uniqe");
+ }
library_prefix.AddImport(ns);
} else {
- library_prefix = LibraryPrefix::New(prefix, ns);
+ library_prefix = LibraryPrefix::New(prefix, ns, is_deferred_import);
library_.AddObject(library_prefix, prefix);
}
}
@@ -9196,14 +9237,17 @@
const String& ident) {
TRACE_PARSER("ResolveIdentInPrefixScope");
HANDLESCOPE(isolate());
- Object& obj = Object::Handle(prefix.LookupObject(ident));
+ Object& obj = Object::Handle();
+ if (prefix.is_loaded()) {
+ obj = prefix.LookupObject(ident);
+ } else {
+ // Remember that this function depends on an import prefix of an
+ // unloaded deferred library.
+ parsed_function()->AddDeferredPrefix(prefix);
+ }
if (obj.IsNull()) {
// Unresolved prefixed primary identifier.
- String& qualified_name = String::ZoneHandle(prefix.name());
- qualified_name = String::Concat(qualified_name, Symbols::Dot());
- qualified_name = String::Concat(qualified_name, ident);
- qualified_name = Symbols::New(qualified_name);
- return new PrimaryNode(ident_pos, qualified_name);
+ return NULL;
} else if (obj.IsClass()) {
const Class& cls = Class::Cast(obj);
return new PrimaryNode(ident_pos, Class::ZoneHandle(cls.raw()));
@@ -9311,7 +9355,8 @@
// Parses type = [ident "."] ident ["<" type { "," type } ">"], then resolve and
// finalize it according to the given type finalization mode.
RawAbstractType* Parser::ParseType(
- ClassFinalizer::FinalizationKind finalization) {
+ ClassFinalizer::FinalizationKind finalization,
+ bool allow_deferred_type) {
TRACE_PARSER("ParseType");
CheckToken(Token::kIDENT, "type name expected");
QualIdent type_name;
@@ -9337,6 +9382,18 @@
"using '%s' in this context is invalid",
type_name.ident->ToCString());
}
+ if ((type_name.lib_prefix != NULL) &&
+ type_name.lib_prefix->is_deferred_load() &&
+ !allow_deferred_type) {
+ ParseTypeArguments(ClassFinalizer::kIgnore);
+ return ClassFinalizer::NewFinalizedMalformedType(
+ Error::Handle(), // No previous error.
+ script_,
+ type_name.ident_pos,
+ "using deferred type '%s.%s' is invalid",
+ String::Handle(type_name.lib_prefix->name()).ToCString(),
+ type_name.ident->ToCString());
+ }
}
Object& type_class = Object::Handle(isolate());
// Leave type_class as null if type finalization mode is kIgnore.
@@ -9895,8 +9952,10 @@
ErrorMsg("type name expected");
}
intptr_t type_pos = TokenPos();
+ // Can't allocate const objects of a deferred type.
+ const bool allow_deferred_type = !is_const;
AbstractType& type = AbstractType::Handle(
- ParseType(ClassFinalizer::kCanonicalizeWellFormed));
+ ParseType(ClassFinalizer::kCanonicalizeWellFormed, allow_deferred_type));
// In case the type is malformed, throw a dynamic type error after finishing
// parsing the instance creation expression.
if (!type.IsMalformed() && (type.IsTypeParameter() || type.IsDynamicType())) {
@@ -10282,6 +10341,7 @@
CloseBlock();
} else if (IsIdentifier()) {
QualIdent qual_ident;
+ intptr_t qual_ident_pos = TokenPos();
ParseQualIdent(&qual_ident);
if (qual_ident.lib_prefix == NULL) {
if (!ResolveIdentInLocalScope(qual_ident.ident_pos,
@@ -10312,30 +10372,42 @@
// Note: unlike in the case of an unqualified identifier, do not
// interpret the unresolved identifier as an instance method or
// instance getter call when compiling an instance method.
- // TODO(hausner): Ideally we should generate the NoSuchMethodError
- // later, when we know more about how the unresolved name is used.
- // For example, we don't know yet whether the unresolved name
- // refers to a getter or a setter. However, it is more awkward
- // to distinuish four NoSuchMethodError cases all over the place
- // in the parser. The four cases are: prefixed vs non-prefixed
- // name, static vs dynamic context in which the unresolved name
- // is used. We cheat a little here by looking at the next token
- // to determine whether we have an unresolved method call or
- // field access.
- if (primary->IsPrimaryNode() &&
- primary->AsPrimaryNode()->primary().IsString()) {
- InvocationMirror::Type call_type =
- CurrentToken() == Token::kLPAREN ?
- InvocationMirror::kMethod : InvocationMirror::kGetter;
- const String& unresolved_name =
- String::Cast(primary->AsPrimaryNode()->primary());
- primary = ThrowNoSuchMethodError(primary->token_pos(),
- current_class(),
- unresolved_name,
- NULL, // No arguments.
- InvocationMirror::kTopLevel,
- call_type,
- NULL); // No existing function.
+ if (primary == NULL) {
+ if (qual_ident.lib_prefix->is_deferred_load() &&
+ qual_ident.ident->Equals(Symbols::LoadLibrary())) {
+ // Hack Alert: recognize special 'loadLibrary' call on the
+ // prefix object. The prefix is the primary. Rewind parser and
+ // let ParseSelectors() handle the loadLibrary call.
+ SetPosition(qual_ident_pos);
+ ConsumeToken(); // Prefix name.
+ primary = new LiteralNode(qual_ident_pos, *qual_ident.lib_prefix);
+ } else {
+ // TODO(hausner): Ideally we should generate the NoSuchMethodError
+ // later, when we know more about how the unresolved name is used.
+ // For example, we don't know yet whether the unresolved name
+ // refers to a getter or a setter. However, it is more awkward
+ // to distinuish four NoSuchMethodError cases all over the place
+ // in the parser. The four cases are: prefixed vs non-prefixed
+ // name, static vs dynamic context in which the unresolved name
+ // is used. We cheat a little here by looking at the next token
+ // to determine whether we have an unresolved method call or
+ // field access.
+ String& qualified_name =
+ String::ZoneHandle(qual_ident.lib_prefix->name());
+ qualified_name = String::Concat(qualified_name, Symbols::Dot());
+ qualified_name = String::Concat(qualified_name, *qual_ident.ident);
+ qualified_name = Symbols::New(qualified_name);
+ InvocationMirror::Type call_type =
+ CurrentToken() == Token::kLPAREN ?
+ InvocationMirror::kMethod : InvocationMirror::kGetter;
+ primary = ThrowNoSuchMethodError(qual_ident_pos,
+ current_class(),
+ qualified_name,
+ NULL, // No arguments.
+ InvocationMirror::kTopLevel,
+ call_type,
+ NULL); // No existing function.
+ }
}
}
ASSERT(primary != NULL);
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index 8760eab..587444a 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -47,6 +47,7 @@
saved_current_context_var_(NULL),
saved_entry_context_var_(NULL),
expression_temp_var_(NULL),
+ deferred_prefixes_(NULL),
first_parameter_index_(0),
first_stack_local_index_(0),
num_copied_params_(0),
@@ -108,6 +109,10 @@
static LocalVariable* CreateExpressionTempVar(intptr_t token_pos);
LocalVariable* EnsureExpressionTemp();
+ bool HasDeferredPrefixes() const { return deferred_prefixes_ != NULL; }
+ GrowableObjectArray* DeferredPrefixes() const { return deferred_prefixes_; }
+ void AddDeferredPrefix(const LibraryPrefix& prefix);
+
int first_parameter_index() const { return first_parameter_index_; }
int first_stack_local_index() const { return first_stack_local_index_; }
int num_copied_params() const { return num_copied_params_; }
@@ -124,6 +129,7 @@
LocalVariable* saved_current_context_var_;
LocalVariable* saved_entry_context_var_;
LocalVariable* expression_temp_var_;
+ GrowableObjectArray* deferred_prefixes_;
int first_parameter_index_;
int first_stack_local_index_;
@@ -356,7 +362,8 @@
void ResolveTypeFromClass(const Class& cls,
ClassFinalizer::FinalizationKind finalization,
AbstractType* type);
- RawAbstractType* ParseType(ClassFinalizer::FinalizationKind finalization);
+ RawAbstractType* ParseType(ClassFinalizer::FinalizationKind finalization,
+ bool allow_deferred_type = false);
void ParseTypeParameters(const Class& cls);
RawTypeArguments* ParseTypeArguments(
ClassFinalizer::FinalizationKind finalization);
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index fcb27ab..5ba26e8 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -26,7 +26,6 @@
V(TokenStream) \
V(Script) \
V(Library) \
- V(LibraryPrefix) \
V(Namespace) \
V(Code) \
V(Instructions) \
@@ -46,6 +45,7 @@
V(UnhandledException) \
V(UnwindError) \
V(Instance) \
+ V(LibraryPrefix) \
V(AbstractType) \
V(Type) \
V(TypeRef) \
@@ -782,19 +782,6 @@
};
-class RawLibraryPrefix : public RawObject {
- RAW_HEAP_OBJECT_IMPLEMENTATION(LibraryPrefix);
-
- RawObject** from() { return reinterpret_cast<RawObject**>(&ptr()->name_); }
- RawString* name_; // library prefix name.
- RawArray* imports_; // libraries imported with this prefix.
- RawObject** to() {
- return reinterpret_cast<RawObject**>(&ptr()->imports_);
- }
- intptr_t num_imports_; // Number of library entries in libraries_.
-};
-
-
class RawNamespace : public RawObject {
RAW_HEAP_OBJECT_IMPLEMENTATION(Namespace);
@@ -1136,6 +1123,23 @@
};
+class RawLibraryPrefix : public RawInstance {
+ RAW_HEAP_OBJECT_IMPLEMENTATION(LibraryPrefix);
+
+ RawObject** from() { return reinterpret_cast<RawObject**>(&ptr()->name_); }
+ RawString* name_; // Library prefix name.
+ RawArray* imports_; // Libraries imported with this prefix.
+ RawArray* dependent_code_; // Code that refers to deferred, unloaded
+ // library prefix.
+ RawObject** to() {
+ return reinterpret_cast<RawObject**>(&ptr()->dependent_code_);
+ }
+ intptr_t num_imports_; // Number of library entries in libraries_.
+ bool is_deferred_load_;
+ bool is_loaded_;
+};
+
+
class RawAbstractType : public RawInstance {
protected:
enum TypeState {
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index e917e67..db45e58 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -1094,6 +1094,8 @@
// Set all non object fields.
prefix.raw_ptr()->num_imports_ = reader->ReadIntptrValue();
+ prefix.raw_ptr()->is_deferred_load_ = reader->Read<bool>();
+ prefix.raw_ptr()->is_loaded_ = reader->Read<bool>();
// Set all the object fields.
// TODO(5411462): Need to assert No GC can happen here, even though
@@ -1119,11 +1121,13 @@
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
- writer->WriteVMIsolateObject(kLibraryPrefixCid);
+ writer->WriteIndexedObject(kLibraryPrefixCid);
writer->WriteIntptrValue(writer->GetObjectTags(this));
// Write out all non object fields.
writer->WriteIntptrValue(ptr()->num_imports_);
+ writer->Write<bool>(ptr()->is_deferred_load_);
+ writer->Write<bool>(ptr()->is_loaded_);
// Write out all the object pointer fields.
SnapshotWriterVisitor visitor(writer);
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index 29d9792..8c0a49e 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -598,7 +598,7 @@
RawLibraryPrefix* SnapshotReader::NewLibraryPrefix() {
- ALLOC_NEW_OBJECT(LibraryPrefix, Object::library_prefix_class());
+ ALLOC_NEW_OBJECT(LibraryPrefix, object_store()->library_prefix_class());
}
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index df5679d..865c77e 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -66,6 +66,8 @@
V(ClosureFunctionField, ":function") \
V(ClosureContextField, ":context") \
V(Library, "library") \
+ V(LoadLibrary, "loadLibrary") \
+ V(_LibraryPrefix, "_LibraryPrefix") \
V(Native, "native") \
V(Import, "import") \
V(Source, "source") \
diff --git a/tests/language/deferred_constraints_type_annotation_test.dart b/tests/language/deferred_constraints_type_annotation_test.dart
index 3fbc238..043f85c 100644
--- a/tests/language/deferred_constraints_type_annotation_test.dart
+++ b/tests/language/deferred_constraints_type_annotation_test.dart
@@ -15,7 +15,7 @@
lib.C a = null; /// type_annotation_null: static type warning
Expect.throws(() { /// new_before_load: static type warning
lib.C a = new lib.C(); /// new_before_load: continued
- }, (e) => e is NoSuchMethodError); /// new_before_load: continued
+ }, (e) => e is Error); /// new_before_load: continued
// In this case we do not defer C.
lib2.C a1 = new lib2.C(); /// type_annotation_non_deferred: continued
diff --git a/tests/language/language.status b/tests/language/language.status
index 8d12238..d505b7d 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -21,16 +21,17 @@
mixin_forwarding_constructor2_test: Fail # Issue 13641
# Issue 17521
-deferred_constraints_constants_test/*: Fail, Pass
-deferred_constraints_type_annotation_test/*: Fail, Pass
-deferred_shadow_load_library_test: Fail
-deferred_closurize_load_library_test: Fail
-deferred_constraints_type_annotation_old_syntax_test/as_operation: Fail
-deferred_constraints_type_annotation_old_syntax_test/is_check: Fail
-deferred_constraints_type_annotation_old_syntax_test/catch_check: Fail
-deferred_constraints_type_annotation_old_syntax_test/new_before_load: Fail
+deferred_constraints_constants_test/default_argument2: Fail
+deferred_constraints_constants_test/metadata1: Fail
+deferred_constraints_constants_test/metadata3: Fail
+deferred_constraints_constants_test/metadata2: Fail
+
# These test use the old syntax, and will be phased out.
+deferred_constraints_type_annotation_old_syntax_test/as_operation: Fail, Ok
+deferred_constraints_type_annotation_old_syntax_test/is_check: Fail, Ok
+deferred_constraints_type_annotation_old_syntax_test/catch_check: Fail, Ok
+deferred_constraints_type_annotation_old_syntax_test/new_before_load: Fail, Ok
deferred_constraints_constants_old_syntax_test/reference1: Fail, Ok
deferred_constraints_constants_old_syntax_test/reference2: Fail, Ok
deferred_constraints_constants_old_syntax_test/metadata1: Fail, Ok
@@ -41,8 +42,12 @@
deferred_constraints_constants_old_syntax_test/constructor1: Fail, Ok
deferred_constraints_constants_old_syntax_test/constructor2: Fail, Ok
-[ ($compiler == none || $compiler == dart2dart)]
-# Issue 17521, 17523
+cyclic_type_test: Fail, Pass # Issue 17629
+cyclic_type2_test: Fail, Pass # Issue 17629
+least_upper_bound_expansive_test/*: Fail, Pass # Issue 17629
+
+[ ($compiler == dart2dart)]
+# Issue 17523
deferred_constraints_type_annotation_test/as_operation: Fail
deferred_constraints_type_annotation_test/is_check: Fail
deferred_constraints_type_annotation_test/catch_check: Fail
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index ae0a1d3..4d091a2 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -250,7 +250,6 @@
mirrors/mixin_application_test/01: Fail, OK # TODO(ahe): Slight broken test to ensure test coverage on dart2js.
mirrors/intercepted_object_test: Fail, OK # TODO(ahe): Slight broken test to ensure test coverage on dart2js.
mirrors/typedef_test/01: Fail, OK # Incorrect dart2js behavior.
-mirrors/deferred_mirrors_metadata_test: Fail # Issue 17521
mirrors/generic_local_function_test: RuntimeError # Issue 14913
mirrors/symbol_validation_test: RuntimeError # Issue 13596
diff --git a/tests/standalone/issue14236_source.dart b/tests/standalone/issue14236_source.dart
index a422cae..3182e48 100644
--- a/tests/standalone/issue14236_source.dart
+++ b/tests/standalone/issue14236_source.dart
@@ -7,8 +7,8 @@
// The original test/main has been commented out and we have a test/main which
// throws an error to ensure that this file is not executed as part of the
// test.
-//
-// When issue14236_test.dart fails, you must regenerate it using the VM
+//
+// When issue14236_test.dart fails, you must regenerate it using the VM
// with your changes. You should understand what in your change makes
// regeneration of the snapshot necessary.
// Steps for regenerating:
@@ -28,7 +28,7 @@
}
*/
-test() {
+test(dummy) {
Expect.fail("Don't expect this to run at all");
}
diff --git a/tests/standalone/issue14236_test.dart b/tests/standalone/issue14236_test.dart
index cb41800..b837d0b 100644
--- a/tests/standalone/issue14236_test.dart
+++ b/tests/standalone/issue14236_test.dart
Binary files differ
diff --git a/tools/VERSION b/tools/VERSION
index c151c3b..c121fd1 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
MINOR 3
PATCH 0
PRERELEASE 7
-PRERELEASE_PATCH 4
+PRERELEASE_PATCH 5