mirror of
https://github.com/dart-lang/sdk
synced 2024-11-05 18:22:09 +00:00
Added full deferred loading semantic to precompiled/--noopt/eager-loading code (some corner cases, e.g., compile-time errors for constants, still missing)
BUG= R=hausner@google.com Review URL: https://codereview.chromium.org//1211273011 .
This commit is contained in:
parent
e5e3d161e7
commit
d503d2f0ed
13 changed files with 169 additions and 32 deletions
|
@ -57,6 +57,18 @@ class _TypeError extends _AssertionError implements TypeError {
|
|||
String error_msg)
|
||||
native "TypeError_throwNew";
|
||||
|
||||
static _throwNewIfNotLoaded(_LibraryPrefix prefix,
|
||||
int location,
|
||||
Object src_value,
|
||||
String dst_type_name,
|
||||
String dst_name,
|
||||
String error_msg) {
|
||||
if (!prefix.isLoaded()) {
|
||||
_throwNew(location, src_value, dst_type_name, dst_name, error_msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String toString() {
|
||||
String str = (_errorMsg != null) ? _errorMsg : "";
|
||||
if ((_dstName != null) && (_dstName.length > 0)) {
|
||||
|
@ -181,6 +193,19 @@ patch class NoSuchMethodError {
|
|||
existingArgumentNames);
|
||||
}
|
||||
|
||||
static void _throwNewIfNotLoaded(_LibraryPrefix prefix,
|
||||
Object receiver,
|
||||
String memberName,
|
||||
int invocation_type,
|
||||
List arguments,
|
||||
List argumentNames,
|
||||
List existingArgumentNames) {
|
||||
if (!prefix.isLoaded()) {
|
||||
_throwNew(receiver, memberName, invocation_type, arguments,
|
||||
argumentNames, existingArgumentNames);
|
||||
}
|
||||
}
|
||||
|
||||
// Remember the type from the invocation mirror or static compilation
|
||||
// analysis when thrown directly with _throwNew. A negative value means
|
||||
// that no information is available.
|
||||
|
|
|
@ -10,6 +10,7 @@ class _LibraryPrefix {
|
|||
|
||||
bool _load() native "LibraryPrefix_load";
|
||||
Error _loadError() native "LibraryPrefix_loadError";
|
||||
bool isLoaded() native "LibraryPrefix_isLoaded";
|
||||
|
||||
bool _invalidateDependentCode()
|
||||
native "LibraryPrefix_invalidateDependentCode";
|
||||
|
|
|
@ -378,6 +378,13 @@ DEFINE_NATIVE_ENTRY(LibraryPrefix_loadError, 1) {
|
|||
}
|
||||
|
||||
|
||||
DEFINE_NATIVE_ENTRY(LibraryPrefix_isLoaded, 1) {
|
||||
const LibraryPrefix& prefix =
|
||||
LibraryPrefix::CheckedHandle(arguments->NativeArgAt(0));
|
||||
return Bool::Get(prefix.is_loaded()).raw();
|
||||
}
|
||||
|
||||
|
||||
DEFINE_NATIVE_ENTRY(Internal_inquireIs64Bit, 0) {
|
||||
#if defined(ARCH_IS_64_BIT)
|
||||
return Bool::True().raw();
|
||||
|
|
|
@ -380,6 +380,7 @@ namespace dart {
|
|||
V(LibraryPrefix_load, 1) \
|
||||
V(LibraryPrefix_invalidateDependentCode, 1) \
|
||||
V(LibraryPrefix_loadError, 1) \
|
||||
V(LibraryPrefix_isLoaded, 1) \
|
||||
V(UserTag_new, 2) \
|
||||
V(UserTag_label, 1) \
|
||||
V(UserTag_defaultTag, 0) \
|
||||
|
|
|
@ -64,6 +64,7 @@ DEFINE_FLAG(bool, use_inlining, true, "Enable call-site inlining");
|
|||
DEFINE_FLAG(bool, verify_compiler, false,
|
||||
"Enable compiler verification assertions");
|
||||
|
||||
DECLARE_FLAG(bool, load_deferred_eagerly);
|
||||
DECLARE_FLAG(bool, trace_failed_optimization_attempts);
|
||||
DECLARE_FLAG(bool, trace_inlining_intervals);
|
||||
DECLARE_FLAG(bool, trace_irregexp);
|
||||
|
@ -71,6 +72,7 @@ DECLARE_FLAG(bool, trace_patching);
|
|||
|
||||
|
||||
bool Compiler::always_optimize_ = false;
|
||||
bool Compiler::allow_recompilation_ = true;
|
||||
|
||||
|
||||
// TODO(zerny): Factor out unoptimizing/optimizing pipelines and remove
|
||||
|
@ -788,6 +790,7 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline,
|
|||
ASSERT(CodePatcher::CodeIsPatchable(code));
|
||||
}
|
||||
if (parsed_function->HasDeferredPrefixes()) {
|
||||
ASSERT(!FLAG_load_deferred_eagerly);
|
||||
ZoneGrowableArray<const LibraryPrefix*>* prefixes =
|
||||
parsed_function->deferred_prefixes();
|
||||
for (intptr_t i = 0; i < prefixes->length(); i++) {
|
||||
|
@ -972,6 +975,11 @@ static RawError* CompileFunctionHelper(CompilationPipeline* pipeline,
|
|||
const Function& function,
|
||||
bool optimized,
|
||||
intptr_t osr_id) {
|
||||
// Check that we optimize if 'Compiler::always_optimize()' is set to true,
|
||||
// except if the function is marked as not optimizable.
|
||||
ASSERT(!function.IsOptimizable() ||
|
||||
!Compiler::always_optimize() || optimized);
|
||||
ASSERT(Compiler::allow_recompilation() || !function.HasCode());
|
||||
LongJumpScope jump;
|
||||
if (setjmp(*jump.Set()) == 0) {
|
||||
Thread* const thread = Thread::Current();
|
||||
|
|
|
@ -90,8 +90,14 @@ class Compiler : public AllStatic {
|
|||
static bool always_optimize() { return always_optimize_; }
|
||||
static void set_always_optimize(bool value) { always_optimize_ = value; }
|
||||
|
||||
static bool allow_recompilation() { return allow_recompilation_; }
|
||||
static void set_allow_recompilation(bool value) {
|
||||
allow_recompilation_ = value;
|
||||
}
|
||||
|
||||
private:
|
||||
static bool always_optimize_;
|
||||
static bool allow_recompilation_;
|
||||
};
|
||||
|
||||
} // namespace dart
|
||||
|
|
|
@ -81,10 +81,14 @@ static void NooptModeHandler(bool value) {
|
|||
FLAG_collect_code = false;
|
||||
FLAG_load_deferred_eagerly = true;
|
||||
FLAG_deoptimize_alot = false; // Used in some tests.
|
||||
FLAG_deoptimize_every = 0; // Used in some tests.
|
||||
FLAG_deoptimize_every = 0; // Used in some tests.
|
||||
FLAG_collect_code = false;
|
||||
FLAG_guess_other_cid = true;
|
||||
Compiler::set_always_optimize(true);
|
||||
// Triggers assert if we try to recompile (e.g., because of deferred
|
||||
// loading, deoptimization, ...). Noopt mode simulates behavior
|
||||
// of precompiled code, therefore do not allow recompilation.
|
||||
Compiler::set_allow_recompilation(false);
|
||||
// TODO(srdjan): Enable CHA deoptimization when eager class finalization is
|
||||
// implemented, either with precompilation or as a special pass.
|
||||
FLAG_use_cha_deopt = false;
|
||||
|
|
|
@ -66,13 +66,15 @@ DEFINE_FLAG(bool, use_field_guards, true, "Guard field cids.");
|
|||
DEFINE_FLAG(bool, use_lib_cache, true, "Use library name cache");
|
||||
DEFINE_FLAG(bool, trace_field_guards, false, "Trace changes in field's cids.");
|
||||
|
||||
DECLARE_FLAG(charp, coverage_dir);
|
||||
DECLARE_FLAG(bool, load_deferred_eagerly);
|
||||
DECLARE_FLAG(bool, show_invisible_frames);
|
||||
DECLARE_FLAG(bool, trace_compiler);
|
||||
DECLARE_FLAG(bool, trace_deoptimization);
|
||||
DECLARE_FLAG(bool, trace_deoptimization_verbose);
|
||||
DECLARE_FLAG(bool, show_invisible_frames);
|
||||
DECLARE_FLAG(charp, coverage_dir);
|
||||
DECLARE_FLAG(bool, write_protect_code);
|
||||
|
||||
|
||||
static const char* kGetterPrefix = "get:";
|
||||
static const intptr_t kGetterPrefixLength = strlen(kGetterPrefix);
|
||||
static const char* kSetterPrefix = "set:";
|
||||
|
@ -10219,7 +10221,7 @@ void LibraryPrefix::AddImport(const Namespace& import) const {
|
|||
|
||||
|
||||
RawObject* LibraryPrefix::LookupObject(const String& name) const {
|
||||
if (!is_loaded()) {
|
||||
if (!is_loaded() && !FLAG_load_deferred_eagerly) {
|
||||
return Object::null();
|
||||
}
|
||||
Array& imports = Array::Handle(this->imports());
|
||||
|
|
|
@ -38,15 +38,17 @@
|
|||
namespace dart {
|
||||
|
||||
DEFINE_FLAG(bool, enable_debug_break, false, "Allow use of break \"message\".");
|
||||
DEFINE_FLAG(bool, enable_mirrors, true,
|
||||
"Disable to make importing dart:mirrors an error.");
|
||||
DEFINE_FLAG(bool, load_deferred_eagerly, false,
|
||||
"Load deferred libraries eagerly.");
|
||||
DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations.");
|
||||
DEFINE_FLAG(bool, warn_mixin_typedef, true, "Warning on legacy mixin typedef.");
|
||||
|
||||
DECLARE_FLAG(bool, lazy_dispatchers);
|
||||
DECLARE_FLAG(bool, load_deferred_eagerly);
|
||||
DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
|
||||
DECLARE_FLAG(bool, warn_on_javascript_compatibility);
|
||||
DEFINE_FLAG(bool, enable_mirrors, true,
|
||||
"Disable to make importing dart:mirrors an error.");
|
||||
DECLARE_FLAG(bool, lazy_dispatchers);
|
||||
|
||||
// Quick access to the current isolate and zone.
|
||||
#define I (isolate())
|
||||
|
@ -172,6 +174,9 @@ void ParsedFunction::SetRegExpCompileData(
|
|||
|
||||
|
||||
void ParsedFunction::AddDeferredPrefix(const LibraryPrefix& prefix) {
|
||||
// 'deferred_prefixes_' are used to invalidate code, but no invalidation is
|
||||
// needed if --load_deferred_eagerly.
|
||||
ASSERT(!FLAG_load_deferred_eagerly);
|
||||
ASSERT(prefix.is_deferred_load());
|
||||
ASSERT(!prefix.is_loaded());
|
||||
for (intptr_t i = 0; i < deferred_prefixes_->length(); i++) {
|
||||
|
@ -10038,8 +10043,19 @@ SequenceNode* Parser::NodeAsSequenceNode(intptr_t sequence_pos,
|
|||
}
|
||||
|
||||
|
||||
AstNode* Parser::ThrowTypeError(intptr_t type_pos, const AbstractType& type) {
|
||||
// Call _throwNewIfNotLoaded if prefix is not NULL, otherwise call _throwNew.
|
||||
AstNode* Parser::ThrowTypeError(intptr_t type_pos, const AbstractType& type,
|
||||
LibraryPrefix* prefix) {
|
||||
ArgumentListNode* arguments = new(Z) ArgumentListNode(type_pos);
|
||||
|
||||
String& method_name = String::Handle(Z);
|
||||
if (prefix == NULL) {
|
||||
method_name = Library::PrivateCoreLibName(Symbols::ThrowNew()).raw();
|
||||
} else {
|
||||
arguments->Add(new(Z) LiteralNode(type_pos, *prefix));
|
||||
method_name = Library::PrivateCoreLibName(
|
||||
Symbols::ThrowNewIfNotLoaded()).raw();
|
||||
}
|
||||
// Location argument.
|
||||
arguments->Add(new(Z) LiteralNode(
|
||||
type_pos, Integer::ZoneHandle(Z, Integer::New(type_pos))));
|
||||
|
@ -10054,20 +10070,29 @@ AstNode* Parser::ThrowTypeError(intptr_t type_pos, const AbstractType& type) {
|
|||
ASSERT(!error.IsNull());
|
||||
arguments->Add(new(Z) LiteralNode(type_pos, String::ZoneHandle(Z,
|
||||
Symbols::New(error.ToErrorCString()))));
|
||||
return MakeStaticCall(Symbols::TypeError(),
|
||||
Library::PrivateCoreLibName(Symbols::ThrowNew()),
|
||||
arguments);
|
||||
return MakeStaticCall(Symbols::TypeError(), method_name, arguments);
|
||||
}
|
||||
|
||||
|
||||
// Call _throwNewIfNotLoaded if prefix is not NULL, otherwise call _throwNew.
|
||||
AstNode* Parser::ThrowNoSuchMethodError(intptr_t call_pos,
|
||||
const Class& cls,
|
||||
const String& function_name,
|
||||
ArgumentListNode* function_arguments,
|
||||
InvocationMirror::Call im_call,
|
||||
InvocationMirror::Type im_type,
|
||||
const Function* func) {
|
||||
const Function* func,
|
||||
const LibraryPrefix* prefix) {
|
||||
ArgumentListNode* arguments = new(Z) ArgumentListNode(call_pos);
|
||||
|
||||
String& method_name = String::Handle(Z);
|
||||
if (prefix == NULL) {
|
||||
method_name = Library::PrivateCoreLibName(Symbols::ThrowNew()).raw();
|
||||
} else {
|
||||
arguments->Add(new(Z) LiteralNode(call_pos, *prefix));
|
||||
method_name = Library::PrivateCoreLibName(
|
||||
Symbols::ThrowNewIfNotLoaded()).raw();
|
||||
}
|
||||
// Object receiver.
|
||||
// If the function is external and dynamic, pass the actual receiver,
|
||||
// otherwise, pass a class literal of the unresolved method's owner.
|
||||
|
@ -10140,9 +10165,7 @@ AstNode* Parser::ThrowNoSuchMethodError(intptr_t call_pos,
|
|||
}
|
||||
arguments->Add(new(Z) LiteralNode(call_pos, array));
|
||||
|
||||
return MakeStaticCall(Symbols::NoSuchMethodError(),
|
||||
Library::PrivateCoreLibName(Symbols::ThrowNew()),
|
||||
arguments);
|
||||
return MakeStaticCall(Symbols::NoSuchMethodError(), method_name, arguments);
|
||||
}
|
||||
|
||||
|
||||
|
@ -11816,7 +11839,7 @@ AstNode* Parser::ResolveIdentInPrefixScope(intptr_t ident_pos,
|
|||
return NULL;
|
||||
}
|
||||
Object& obj = Object::Handle(Z);
|
||||
if (prefix.is_loaded()) {
|
||||
if (prefix.is_loaded() || FLAG_load_deferred_eagerly) {
|
||||
obj = prefix.LookupObject(ident);
|
||||
} else {
|
||||
// Remember that this function depends on an import prefix of an
|
||||
|
@ -11952,16 +11975,25 @@ AstNode* Parser::ResolveIdent(intptr_t ident_pos,
|
|||
}
|
||||
|
||||
|
||||
// Parses type = [ident "."] ident ["<" type { "," type } ">"], then resolve and
|
||||
// finalize it according to the given type finalization mode.
|
||||
RawAbstractType* Parser::ParseType(
|
||||
ClassFinalizer::FinalizationKind finalization,
|
||||
bool allow_deferred_type,
|
||||
bool consume_unresolved_prefix) {
|
||||
LibraryPrefix& prefix = LibraryPrefix::Handle(Z);
|
||||
return ParseType(finalization, allow_deferred_type,
|
||||
consume_unresolved_prefix, &prefix);
|
||||
}
|
||||
|
||||
// Parses type = [ident "."] ident ["<" type { "," type } ">"], then resolve and
|
||||
// finalize it according to the given type finalization mode. Returns prefix.
|
||||
RawAbstractType* Parser::ParseType(
|
||||
ClassFinalizer::FinalizationKind finalization,
|
||||
bool allow_deferred_type,
|
||||
bool consume_unresolved_prefix,
|
||||
LibraryPrefix* prefix) {
|
||||
TRACE_PARSER("ParseType");
|
||||
CheckToken(Token::kIDENT, "type name expected");
|
||||
intptr_t ident_pos = TokenPos();
|
||||
LibraryPrefix& prefix = LibraryPrefix::Handle(Z);
|
||||
String& type_name = String::Handle(Z);
|
||||
|
||||
if (finalization == ClassFinalizer::kIgnore) {
|
||||
|
@ -11972,7 +12004,7 @@ RawAbstractType* Parser::ParseType(
|
|||
}
|
||||
SkipQualIdent();
|
||||
} else {
|
||||
prefix = ParsePrefix();
|
||||
*prefix = ParsePrefix();
|
||||
type_name = CurrentLiteral()->raw();
|
||||
ConsumeToken();
|
||||
|
||||
|
@ -11982,7 +12014,7 @@ RawAbstractType* Parser::ParseType(
|
|||
// a period and another identifier, consume the qualified identifier
|
||||
// and create a malformed type.
|
||||
if (consume_unresolved_prefix &&
|
||||
prefix.IsNull() &&
|
||||
prefix->IsNull() &&
|
||||
(CurrentToken() == Token::kPERIOD) &&
|
||||
(Token::IsIdentifier(LookaheadToken(1)))) {
|
||||
if (!is_top_level_ && (current_block_ != NULL)) {
|
||||
|
@ -12009,7 +12041,7 @@ RawAbstractType* Parser::ParseType(
|
|||
// If parsing inside a local scope, check whether the type name
|
||||
// is shadowed by a local declaration.
|
||||
if (!is_top_level_ &&
|
||||
(prefix.IsNull()) &&
|
||||
(prefix->IsNull()) &&
|
||||
ResolveIdentInLocalScope(ident_pos, type_name, NULL)) {
|
||||
// The type is malformed. Skip over its type arguments.
|
||||
ParseTypeArguments(ClassFinalizer::kIgnore);
|
||||
|
@ -12020,29 +12052,30 @@ RawAbstractType* Parser::ParseType(
|
|||
"using '%s' in this context is invalid",
|
||||
type_name.ToCString());
|
||||
}
|
||||
if (!prefix.IsNull() && prefix.is_deferred_load()) {
|
||||
if (!FLAG_load_deferred_eagerly &&
|
||||
!prefix->IsNull() && prefix->is_deferred_load()) {
|
||||
// If deferred prefixes are allowed but it is not yet loaded,
|
||||
// remember that this function depends on the prefix.
|
||||
if (allow_deferred_type && !prefix.is_loaded()) {
|
||||
if (allow_deferred_type && !prefix->is_loaded()) {
|
||||
if (parsed_function() != NULL) {
|
||||
parsed_function()->AddDeferredPrefix(prefix);
|
||||
parsed_function()->AddDeferredPrefix(*prefix);
|
||||
}
|
||||
}
|
||||
// If the deferred prefixes are not allowed, or if the prefix is not yet
|
||||
// loaded when finalization is requested, return a malformed type.
|
||||
// Otherwise, handle resolution below, as needed.
|
||||
if (!allow_deferred_type ||
|
||||
(!prefix.is_loaded()
|
||||
(!prefix->is_loaded()
|
||||
&& (finalization > ClassFinalizer::kResolveTypeParameters))) {
|
||||
ParseTypeArguments(ClassFinalizer::kIgnore);
|
||||
return ClassFinalizer::NewFinalizedMalformedType(
|
||||
Error::Handle(Z), // No previous error.
|
||||
script_,
|
||||
ident_pos,
|
||||
!prefix.is_loaded()
|
||||
!prefix->is_loaded()
|
||||
? "deferred type '%s.%s' is not yet loaded"
|
||||
: "using deferred type '%s.%s' is invalid",
|
||||
String::Handle(Z, prefix.name()).ToCString(),
|
||||
String::Handle(Z, prefix->name()).ToCString(),
|
||||
type_name.ToCString());
|
||||
}
|
||||
}
|
||||
|
@ -12050,7 +12083,7 @@ RawAbstractType* Parser::ParseType(
|
|||
Object& type_class = Object::Handle(Z);
|
||||
// Leave type_class as null if type finalization mode is kIgnore.
|
||||
if (finalization != ClassFinalizer::kIgnore) {
|
||||
type_class = UnresolvedClass::New(prefix, type_name, ident_pos);
|
||||
type_class = UnresolvedClass::New(*prefix, type_name, ident_pos);
|
||||
}
|
||||
TypeArguments& type_arguments = TypeArguments::Handle(
|
||||
Z, ParseTypeArguments(finalization));
|
||||
|
@ -12599,10 +12632,28 @@ AstNode* Parser::ParseNewOperator(Token::Kind op_kind) {
|
|||
const bool allow_deferred_type = !is_const;
|
||||
const bool consume_unresolved_prefix = (LookaheadToken(3) == Token::kLT) ||
|
||||
(LookaheadToken(3) == Token::kPERIOD);
|
||||
LibraryPrefix& prefix = LibraryPrefix::ZoneHandle(Z);
|
||||
AbstractType& type = AbstractType::Handle(Z,
|
||||
ParseType(ClassFinalizer::kCanonicalizeWellFormed,
|
||||
allow_deferred_type,
|
||||
consume_unresolved_prefix));
|
||||
consume_unresolved_prefix,
|
||||
&prefix));
|
||||
if (FLAG_load_deferred_eagerly &&
|
||||
!prefix.IsNull() && prefix.is_deferred_load() && !prefix.is_loaded()) {
|
||||
// Add runtime check.
|
||||
Type& malformed_type = Type::Handle(Z);
|
||||
malformed_type = ClassFinalizer::NewFinalizedMalformedType(
|
||||
Error::Handle(Z), // No previous error.
|
||||
script_,
|
||||
type_pos,
|
||||
"deferred type '%s.%s' is not yet loaded",
|
||||
String::Handle(Z, prefix.name()).ToCString(),
|
||||
String::Handle(type.Name()).ToCString());
|
||||
// Note: Adding a statement to current block is a hack, parsing an
|
||||
// expression should have no side-effect.
|
||||
current_block_->statements->Add(
|
||||
ThrowTypeError(type_pos, malformed_type, &prefix));
|
||||
}
|
||||
// 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())) {
|
||||
|
@ -13083,6 +13134,26 @@ AstNode* Parser::ParsePrimary() {
|
|||
call_type,
|
||||
NULL); // No existing function.
|
||||
}
|
||||
} else if (FLAG_load_deferred_eagerly && prefix.is_deferred_load()) {
|
||||
// primary != NULL.
|
||||
String& qualified_name = String::ZoneHandle(Z, prefix.name());
|
||||
qualified_name = String::Concat(qualified_name, Symbols::Dot());
|
||||
qualified_name = String::Concat(qualified_name, ident);
|
||||
qualified_name = Symbols::New(qualified_name);
|
||||
InvocationMirror::Type call_type =
|
||||
CurrentToken() == Token::kLPAREN ?
|
||||
InvocationMirror::kMethod : InvocationMirror::kGetter;
|
||||
// Note: Adding a statement to current block is a hack, parsing an
|
||||
// espression should have no side-effect.
|
||||
current_block_->statements->Add(ThrowNoSuchMethodError(
|
||||
qual_ident_pos,
|
||||
current_class(),
|
||||
qualified_name,
|
||||
NULL, // No arguments.
|
||||
InvocationMirror::kTopLevel,
|
||||
call_type,
|
||||
NULL, // No existing function.
|
||||
&prefix));
|
||||
}
|
||||
}
|
||||
ASSERT(primary != NULL);
|
||||
|
|
|
@ -432,6 +432,12 @@ class Parser : public ValueObject {
|
|||
RawAbstractType* ParseType(ClassFinalizer::FinalizationKind finalization,
|
||||
bool allow_deferred_type = false,
|
||||
bool consume_unresolved_prefix = true);
|
||||
RawAbstractType* ParseType(
|
||||
ClassFinalizer::FinalizationKind finalization,
|
||||
bool allow_deferred_type,
|
||||
bool consume_unresolved_prefix,
|
||||
LibraryPrefix* prefix);
|
||||
|
||||
void ParseTypeParameters(const Class& cls);
|
||||
RawTypeArguments* ParseTypeArguments(
|
||||
ClassFinalizer::FinalizationKind finalization);
|
||||
|
@ -763,14 +769,16 @@ class Parser : public ValueObject {
|
|||
ArgumentListNode* arguments);
|
||||
String& Interpolate(const GrowableArray<AstNode*>& values);
|
||||
AstNode* MakeAssertCall(intptr_t begin, intptr_t end);
|
||||
AstNode* ThrowTypeError(intptr_t type_pos, const AbstractType& type);
|
||||
AstNode* ThrowTypeError(intptr_t type_pos, const AbstractType& type,
|
||||
LibraryPrefix* prefix = NULL);
|
||||
AstNode* ThrowNoSuchMethodError(intptr_t call_pos,
|
||||
const Class& cls,
|
||||
const String& function_name,
|
||||
ArgumentListNode* function_arguments,
|
||||
InvocationMirror::Call call,
|
||||
InvocationMirror::Type type,
|
||||
const Function* func);
|
||||
const Function* func,
|
||||
const LibraryPrefix* prefix = NULL);
|
||||
|
||||
void SetupSavedTryContext(LocalVariable* saved_try_context);
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@ class ObjectPointerVisitor;
|
|||
V(NoSuchMethodError, "NoSuchMethodError") \
|
||||
V(CyclicInitializationError, "CyclicInitializationError") \
|
||||
V(ThrowNew, "_throwNew") \
|
||||
V(ThrowNewIfNotLoaded, "_throwNewIfNotLoaded") \
|
||||
V(Symbol, "Symbol") \
|
||||
V(SymbolCtor, "Symbol.") \
|
||||
V(List, "List") \
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "vm/code_generator.h"
|
||||
#include "vm/code_patcher.h"
|
||||
#include "vm/compiler.h"
|
||||
#include "vm/object.h"
|
||||
#include "vm/stack_frame.h"
|
||||
|
||||
|
@ -60,6 +61,7 @@ void WeakCodeReferences::DisableCode() {
|
|||
if (code_objects.IsNull()) {
|
||||
return;
|
||||
}
|
||||
ASSERT(Compiler::allow_recompilation());
|
||||
UpdateArrayTo(Object::null_array());
|
||||
// Disable all code on stack.
|
||||
Code& code = Code::Handle();
|
||||
|
|
|
@ -14,6 +14,7 @@ import "deferred_static_seperate_lib2.dart" deferred as lib2;
|
|||
|
||||
void main() {
|
||||
asyncStart();
|
||||
Expect.throws(() => new lib1.C());
|
||||
lib1.loadLibrary().then((_) {
|
||||
lib2.loadLibrary().then((_) {
|
||||
print("HERE");
|
||||
|
|
Loading…
Reference in a new issue