mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 23:29:47 +00:00
Reland "[VM] Remove unused flags"
This is a reland of 1a4cff1bd4
Original change's description:
> [VM] Remove unused flags
>
> Remove the following flags which are always ON
> --strong
> --reify_generic_functions
>
> and these flags which are not applicable anymore
> --error-on-bad-override
> --error-on-bad-type
> --enable-type-checks
>
> Change-Id: I6e1aeb68e663953f4ae49ca94ea0daa87b661900
> Reviewed-on: https://dart-review.googlesource.com/c/79431
> Commit-Queue: Siva Annamalai <asiva@google.com>
> Reviewed-by: Alexander Markov <alexmarkov@google.com>
> Reviewed-by: Régis Crelier <regis@google.com>
Change-Id: Ib4452c22fb05eed38820708abb648939e03b1df0
Reviewed-on: https://dart-review.googlesource.com/c/84923
Reviewed-by: Siva Annamalai <asiva@google.com>
This commit is contained in:
parent
b0730135ff
commit
0ca1c57593
|
@ -246,12 +246,6 @@ class Run extends Step<Uri, int, FastaContext> {
|
||||||
StdioProcess process;
|
StdioProcess process;
|
||||||
try {
|
try {
|
||||||
var args = <String>[];
|
var args = <String>[];
|
||||||
if (!context.legacyMode) {
|
|
||||||
// TODO(ahe): This argument is probably ignored by the VM.
|
|
||||||
args.add('--strong');
|
|
||||||
// TODO(ahe): This argument is probably ignored by the VM.
|
|
||||||
args.add('--reify-generic-functions');
|
|
||||||
}
|
|
||||||
args.add(generated.path);
|
args.add(generated.path);
|
||||||
process = await StdioProcess.run(context.vm.toFilePath(), args);
|
process = await StdioProcess.run(context.vm.toFilePath(), args);
|
||||||
print(process.output);
|
print(process.output);
|
||||||
|
|
|
@ -553,13 +553,11 @@ typedef struct {
|
||||||
* for each part.
|
* for each part.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define DART_FLAGS_CURRENT_VERSION (0x00000009)
|
#define DART_FLAGS_CURRENT_VERSION (0x0000000a)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int32_t version;
|
int32_t version;
|
||||||
bool enable_type_checks;
|
|
||||||
bool enable_asserts;
|
bool enable_asserts;
|
||||||
bool enable_error_on_bad_type;
|
|
||||||
bool use_field_guards;
|
bool use_field_guards;
|
||||||
bool use_osr;
|
bool use_osr;
|
||||||
bool obfuscate;
|
bool obfuscate;
|
||||||
|
|
|
@ -353,11 +353,8 @@ DEFINE_NATIVE_ENTRY(Isolate_spawnUri, 12) {
|
||||||
// If we were passed a value then override the default flags state for
|
// If we were passed a value then override the default flags state for
|
||||||
// checked mode.
|
// checked mode.
|
||||||
if (!checked.IsNull()) {
|
if (!checked.IsNull()) {
|
||||||
bool is_checked = checked.value();
|
|
||||||
Dart_IsolateFlags* flags = state->isolate_flags();
|
Dart_IsolateFlags* flags = state->isolate_flags();
|
||||||
flags->enable_asserts = is_checked;
|
flags->enable_asserts = checked.value();
|
||||||
// Do not enable type checks in strong mode.
|
|
||||||
flags->enable_type_checks = is_checked && !FLAG_strong;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadPool::Task* spawn_task = new SpawnIsolateTask(state);
|
ThreadPool::Task* spawn_task = new SpawnIsolateTask(state);
|
||||||
|
|
|
@ -320,27 +320,24 @@ DEFINE_NATIVE_ENTRY(Internal_extractTypeArguments, 2) {
|
||||||
Instance::CheckedHandle(zone, arguments->NativeArgAt(1));
|
Instance::CheckedHandle(zone, arguments->NativeArgAt(1));
|
||||||
|
|
||||||
Class& interface_cls = Class::Handle(zone);
|
Class& interface_cls = Class::Handle(zone);
|
||||||
intptr_t num_type_args = 0; // Remains 0 when executing Dart 1.0 code.
|
intptr_t num_type_args = 0;
|
||||||
// TODO(regis): Check for strong mode too?
|
const TypeArguments& function_type_args =
|
||||||
if (FLAG_reify_generic_functions) {
|
TypeArguments::Handle(zone, arguments->NativeTypeArgs());
|
||||||
const TypeArguments& function_type_args =
|
if (function_type_args.Length() == 1) {
|
||||||
TypeArguments::Handle(zone, arguments->NativeTypeArgs());
|
const AbstractType& function_type_arg =
|
||||||
if (function_type_args.Length() == 1) {
|
AbstractType::Handle(zone, function_type_args.TypeAt(0));
|
||||||
const AbstractType& function_type_arg =
|
if (function_type_arg.IsType() &&
|
||||||
AbstractType::Handle(zone, function_type_args.TypeAt(0));
|
(function_type_arg.arguments() == TypeArguments::null())) {
|
||||||
if (function_type_arg.IsType() &&
|
interface_cls = function_type_arg.type_class();
|
||||||
(function_type_arg.arguments() == TypeArguments::null())) {
|
num_type_args = interface_cls.NumTypeParameters();
|
||||||
interface_cls = function_type_arg.type_class();
|
|
||||||
num_type_args = interface_cls.NumTypeParameters();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (num_type_args == 0) {
|
|
||||||
Exceptions::ThrowArgumentError(String::Handle(
|
|
||||||
zone,
|
|
||||||
String::New(
|
|
||||||
"single function type argument must specify a generic class")));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (num_type_args == 0) {
|
||||||
|
Exceptions::ThrowArgumentError(String::Handle(
|
||||||
|
zone,
|
||||||
|
String::New(
|
||||||
|
"single function type argument must specify a generic class")));
|
||||||
|
}
|
||||||
if (instance.IsNull()) {
|
if (instance.IsNull()) {
|
||||||
Exceptions::ThrowArgumentError(instance);
|
Exceptions::ThrowArgumentError(instance);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
namespace dart {
|
namespace dart {
|
||||||
|
|
||||||
DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes.");
|
DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes.");
|
||||||
DEFINE_FLAG(bool, reify, true, "Reify type arguments of generic types.");
|
|
||||||
DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization.");
|
DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization.");
|
||||||
DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization.");
|
DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization.");
|
||||||
|
|
||||||
|
@ -485,12 +484,6 @@ void ClassFinalizer::ResolveTypeClass(const Class& cls, const Type& type) {
|
||||||
}
|
}
|
||||||
ASSERT(!type_class.IsTypedefClass() ||
|
ASSERT(!type_class.IsTypedefClass() ||
|
||||||
(type.signature() != Function::null()));
|
(type.signature() != Function::null()));
|
||||||
|
|
||||||
// In non-strong mode, replace FutureOr<T> type of async library with dynamic.
|
|
||||||
if (type_class.IsFutureOrClass() && !FLAG_strong) {
|
|
||||||
Type::Cast(type).set_type_class(Class::Handle(Object::dynamic_class()));
|
|
||||||
type.set_arguments(Object::null_type_arguments());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassFinalizer::ResolveType(const Class& cls, const AbstractType& type) {
|
void ClassFinalizer::ResolveType(const Class& cls, const AbstractType& type) {
|
||||||
|
@ -708,26 +701,15 @@ intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments(
|
||||||
// The class has num_type_parameters type parameters.
|
// The class has num_type_parameters type parameters.
|
||||||
const intptr_t num_type_parameters = type_class.NumTypeParameters();
|
const intptr_t num_type_parameters = type_class.NumTypeParameters();
|
||||||
|
|
||||||
// If we are not reifying types, drop type arguments.
|
|
||||||
if (!FLAG_reify) {
|
|
||||||
type.set_arguments(Object::null_type_arguments());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize the type argument vector.
|
// Initialize the type argument vector.
|
||||||
// Check the number of parsed type arguments, if any.
|
// Check the number of parsed type arguments, if any.
|
||||||
// Specifying no type arguments indicates a raw type, which is not an error.
|
// Specifying no type arguments indicates a raw type, which is not an error.
|
||||||
// However, type parameter bounds are checked below, even for a raw type.
|
// However, type parameter bounds are checked below, even for a raw type.
|
||||||
TypeArguments& arguments = TypeArguments::Handle(zone, type.arguments());
|
TypeArguments& arguments = TypeArguments::Handle(zone, type.arguments());
|
||||||
if (!arguments.IsNull() && (arguments.Length() != num_type_parameters)) {
|
if (!arguments.IsNull() && (arguments.Length() != num_type_parameters)) {
|
||||||
// Wrong number of type arguments. The type is mapped to the raw type.
|
|
||||||
if (Isolate::Current()->error_on_bad_type()) {
|
|
||||||
const String& type_class_name = String::Handle(zone, type_class.Name());
|
|
||||||
ReportError(cls, type.token_pos(),
|
|
||||||
"wrong number of type arguments for class '%s'",
|
|
||||||
type_class_name.ToCString());
|
|
||||||
}
|
|
||||||
// Make the type raw and continue without reporting any error.
|
// Make the type raw and continue without reporting any error.
|
||||||
// A static warning should have been reported.
|
// A static warning should have been reported.
|
||||||
|
// TODO(regis): Check if this is dead code.
|
||||||
arguments = TypeArguments::null();
|
arguments = TypeArguments::null();
|
||||||
type.set_arguments(arguments);
|
type.set_arguments(arguments);
|
||||||
}
|
}
|
||||||
|
@ -743,7 +725,7 @@ intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments(
|
||||||
// super types of type_class, which are initialized from the parsed
|
// super types of type_class, which are initialized from the parsed
|
||||||
// type arguments, followed by the parsed type arguments.
|
// type arguments, followed by the parsed type arguments.
|
||||||
TypeArguments& full_arguments = TypeArguments::Handle(zone);
|
TypeArguments& full_arguments = TypeArguments::Handle(zone);
|
||||||
if (FLAG_reify && (num_type_arguments > 0)) {
|
if (num_type_arguments > 0) {
|
||||||
// If no type arguments were parsed and if the super types do not prepend
|
// If no type arguments were parsed and if the super types do not prepend
|
||||||
// type arguments to the vector, we can leave the vector as null.
|
// type arguments to the vector, we can leave the vector as null.
|
||||||
if (!arguments.IsNull() || (num_type_arguments > num_type_parameters)) {
|
if (!arguments.IsNull() || (num_type_arguments > num_type_parameters)) {
|
||||||
|
@ -981,162 +963,6 @@ void ClassFinalizer::FinalizeTypeArguments(const Class& cls,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the type argument vector 'arguments' against the corresponding bounds
|
|
||||||
// of the type parameters of class 'cls' and, recursively, of its superclasses.
|
|
||||||
// Replace a type argument that cannot be checked at compile time by a
|
|
||||||
// BoundedType, thereby postponing the bound check to run time.
|
|
||||||
// Return a bound error if a type argument is not within bound at compile time.
|
|
||||||
void ClassFinalizer::CheckTypeArgumentBounds(const Class& cls,
|
|
||||||
const TypeArguments& arguments,
|
|
||||||
Error* bound_error) {
|
|
||||||
if (!cls.is_type_finalized()) {
|
|
||||||
FinalizeTypeParameters(cls);
|
|
||||||
FinalizeUpperBounds(cls, kFinalize); // No canonicalization yet.
|
|
||||||
}
|
|
||||||
// Note that when finalizing a type, we need to verify the bounds in both
|
|
||||||
// production mode and checked mode, because the finalized type may be written
|
|
||||||
// to a snapshot. It would be wrong to ignore bounds when generating the
|
|
||||||
// snapshot in production mode and then use the unchecked type in checked mode
|
|
||||||
// after reading it from the snapshot.
|
|
||||||
// However, we do not immediately report a bound error, which would be wrong
|
|
||||||
// in production mode, but simply postpone the bound checking to runtime.
|
|
||||||
const intptr_t num_type_params = cls.NumTypeParameters();
|
|
||||||
const intptr_t offset = cls.NumTypeArguments() - num_type_params;
|
|
||||||
AbstractType& type_arg = AbstractType::Handle();
|
|
||||||
AbstractType& cls_type_param = AbstractType::Handle();
|
|
||||||
AbstractType& declared_bound = AbstractType::Handle();
|
|
||||||
AbstractType& instantiated_bound = AbstractType::Handle();
|
|
||||||
const TypeArguments& cls_type_params =
|
|
||||||
TypeArguments::Handle(cls.type_parameters());
|
|
||||||
ASSERT((cls_type_params.IsNull() && (num_type_params == 0)) ||
|
|
||||||
(cls_type_params.Length() == num_type_params));
|
|
||||||
// In case of overlapping type argument vectors, the same type argument may
|
|
||||||
// get checked against different bounds.
|
|
||||||
for (intptr_t i = 0; i < num_type_params; i++) {
|
|
||||||
type_arg = arguments.TypeAt(offset + i);
|
|
||||||
if (type_arg.IsDynamicType()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ASSERT(type_arg.IsFinalized());
|
|
||||||
if (type_arg.IsMalbounded()) {
|
|
||||||
// The type argument itself is already malbounded, independently of the
|
|
||||||
// declared bound, which may be Object.
|
|
||||||
// Propagate the bound error from the type argument to the type.
|
|
||||||
if (bound_error->IsNull()) {
|
|
||||||
*bound_error = type_arg.error();
|
|
||||||
ASSERT(!bound_error->IsNull());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cls_type_param = cls_type_params.TypeAt(i);
|
|
||||||
const TypeParameter& type_param = TypeParameter::Cast(cls_type_param);
|
|
||||||
ASSERT(type_param.IsFinalized());
|
|
||||||
declared_bound = type_param.bound();
|
|
||||||
if (!declared_bound.IsObjectType() && !declared_bound.IsDynamicType()) {
|
|
||||||
if (!declared_bound.IsFinalized() && !declared_bound.IsBeingFinalized()) {
|
|
||||||
declared_bound = FinalizeType(cls, declared_bound);
|
|
||||||
type_param.set_bound(declared_bound);
|
|
||||||
}
|
|
||||||
ASSERT(declared_bound.IsFinalized() || declared_bound.IsBeingFinalized());
|
|
||||||
Error& error = Error::Handle();
|
|
||||||
// Note that the bound may be malformed, in which case the bound check
|
|
||||||
// will return an error and the bound check will be postponed to run time.
|
|
||||||
if (declared_bound.IsInstantiated()) {
|
|
||||||
instantiated_bound = declared_bound.raw();
|
|
||||||
} else {
|
|
||||||
instantiated_bound = declared_bound.InstantiateFrom(
|
|
||||||
arguments, Object::null_type_arguments(), kNoneFree, &error, NULL,
|
|
||||||
NULL, Heap::kOld);
|
|
||||||
}
|
|
||||||
if (!instantiated_bound.IsFinalized()) {
|
|
||||||
// The bound refers to type parameters, creating a cycle; postpone
|
|
||||||
// bound check to run time, when the bound will be finalized.
|
|
||||||
// The bound may not necessarily be 'IsBeingFinalized' yet, as is the
|
|
||||||
// case with a pair of type parameters of the same class referring to
|
|
||||||
// each other via their bounds.
|
|
||||||
type_arg = BoundedType::New(type_arg, instantiated_bound, type_param);
|
|
||||||
arguments.SetTypeAt(offset + i, type_arg);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Shortcut the special case where we check a type parameter against its
|
|
||||||
// declared upper bound.
|
|
||||||
if (error.IsNull() && !(type_arg.Equals(type_param) &&
|
|
||||||
instantiated_bound.Equals(declared_bound))) {
|
|
||||||
// If type_arg is a type parameter, its declared bound may not be
|
|
||||||
// finalized yet.
|
|
||||||
if (type_arg.IsTypeParameter()) {
|
|
||||||
const Class& type_arg_cls = Class::Handle(
|
|
||||||
TypeParameter::Cast(type_arg).parameterized_class());
|
|
||||||
AbstractType& bound =
|
|
||||||
AbstractType::Handle(TypeParameter::Cast(type_arg).bound());
|
|
||||||
if (!bound.IsFinalized() && !bound.IsBeingFinalized()) {
|
|
||||||
bound = FinalizeType(type_arg_cls, bound);
|
|
||||||
TypeParameter::Cast(type_arg).set_bound(bound);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// This may be called only if type needs to be finalized, therefore
|
|
||||||
// seems OK to allocate finalized types in old space.
|
|
||||||
if (!type_param.CheckBound(type_arg, instantiated_bound, &error, NULL,
|
|
||||||
Heap::kOld) &&
|
|
||||||
error.IsNull()) {
|
|
||||||
// The bound cannot be checked at compile time; postpone to run time.
|
|
||||||
type_arg = BoundedType::New(type_arg, instantiated_bound, type_param);
|
|
||||||
arguments.SetTypeAt(offset + i, type_arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!error.IsNull() && bound_error->IsNull()) {
|
|
||||||
*bound_error = error.raw();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AbstractType& super_type = AbstractType::Handle(cls.super_type());
|
|
||||||
if (!super_type.IsNull() && !super_type.IsBeingFinalized()) {
|
|
||||||
const Class& super_class = Class::Handle(super_type.type_class());
|
|
||||||
CheckTypeArgumentBounds(super_class, arguments, bound_error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClassFinalizer::CheckTypeBounds(const Class& cls,
|
|
||||||
const AbstractType& type) {
|
|
||||||
Zone* zone = Thread::Current()->zone();
|
|
||||||
ASSERT(type.IsType());
|
|
||||||
ASSERT(type.IsFinalized());
|
|
||||||
ASSERT(!type.IsCanonical());
|
|
||||||
TypeArguments& arguments = TypeArguments::Handle(zone, type.arguments());
|
|
||||||
if (arguments.IsNull()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (FLAG_trace_type_finalization) {
|
|
||||||
THR_Print("Checking bounds of type '%s' for class '%s'\n",
|
|
||||||
String::Handle(zone, type.Name()).ToCString(),
|
|
||||||
String::Handle(zone, cls.Name()).ToCString());
|
|
||||||
}
|
|
||||||
const Class& type_class = Class::Handle(zone, type.type_class());
|
|
||||||
Error& bound_error = Error::Handle(zone);
|
|
||||||
CheckTypeArgumentBounds(type_class, arguments, &bound_error);
|
|
||||||
// CheckTypeArgumentBounds may have indirectly canonicalized this type.
|
|
||||||
if (!type.IsCanonical()) {
|
|
||||||
type.set_arguments(arguments);
|
|
||||||
// If a bound error occurred, mark the type as malbounded.
|
|
||||||
// The bound error will be ignored in production mode.
|
|
||||||
if (!bound_error.IsNull()) {
|
|
||||||
// No compile-time error during finalization.
|
|
||||||
const String& type_name = String::Handle(zone, type.UserVisibleName());
|
|
||||||
FinalizeMalboundedType(
|
|
||||||
bound_error, Script::Handle(zone, cls.script()), type,
|
|
||||||
"type '%s' has an out of bound type argument", type_name.ToCString());
|
|
||||||
if (FLAG_trace_type_finalization) {
|
|
||||||
THR_Print("Marking type '%s' as malbounded: %s\n",
|
|
||||||
String::Handle(zone, type.Name()).ToCString(),
|
|
||||||
bound_error.ToErrorCString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (FLAG_trace_type_finalization) {
|
|
||||||
THR_Print("Done checking bounds of type '%s': %s\n",
|
|
||||||
String::Handle(zone, type.Name()).ToCString(), type.ToCString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RawAbstractType* ClassFinalizer::FinalizeType(const Class& cls,
|
RawAbstractType* ClassFinalizer::FinalizeType(const Class& cls,
|
||||||
const AbstractType& type,
|
const AbstractType& type,
|
||||||
FinalizationKind finalization,
|
FinalizationKind finalization,
|
||||||
|
@ -1149,9 +975,6 @@ RawAbstractType* ClassFinalizer::FinalizeType(const Class& cls,
|
||||||
// malformed.
|
// malformed.
|
||||||
if ((finalization >= kCanonicalize) && !type.IsMalformed() &&
|
if ((finalization >= kCanonicalize) && !type.IsMalformed() &&
|
||||||
!type.IsCanonical() && type.IsType()) {
|
!type.IsCanonical() && type.IsType()) {
|
||||||
if (!FLAG_strong) {
|
|
||||||
CheckTypeBounds(cls, type);
|
|
||||||
}
|
|
||||||
return type.Canonicalize();
|
return type.Canonicalize();
|
||||||
}
|
}
|
||||||
return type.raw();
|
return type.raw();
|
||||||
|
@ -1291,17 +1114,6 @@ RawAbstractType* ClassFinalizer::FinalizeType(const Class& cls,
|
||||||
type.SetIsFinalized();
|
type.SetIsFinalized();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are done finalizing a graph of mutually recursive types, check their
|
|
||||||
// bounds.
|
|
||||||
if (is_root_type && !FLAG_strong) {
|
|
||||||
for (intptr_t i = pending_types->length() - 1; i >= 0; i--) {
|
|
||||||
const AbstractType& type = pending_types->At(i);
|
|
||||||
if (!type.IsMalformed() && !type.IsCanonical()) {
|
|
||||||
CheckTypeBounds(cls, type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FLAG_trace_type_finalization) {
|
if (FLAG_trace_type_finalization) {
|
||||||
THR_Print("Done finalizing type '%s' with %" Pd " type args: %s\n",
|
THR_Print("Done finalizing type '%s' with %" Pd " type args: %s\n",
|
||||||
String::Handle(zone, type.Name()).ToCString(),
|
String::Handle(zone, type.Name()).ToCString(),
|
||||||
|
@ -1507,7 +1319,7 @@ void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) {
|
||||||
Field& field = Field::Handle(zone);
|
Field& field = Field::Handle(zone);
|
||||||
AbstractType& type = AbstractType::Handle(zone);
|
AbstractType& type = AbstractType::Handle(zone);
|
||||||
const intptr_t num_fields = array.Length();
|
const intptr_t num_fields = array.Length();
|
||||||
const bool track_exactness = FLAG_strong && isolate->use_field_guards();
|
const bool track_exactness = isolate->use_field_guards();
|
||||||
for (intptr_t i = 0; i < num_fields; i++) {
|
for (intptr_t i = 0; i < num_fields; i++) {
|
||||||
field ^= array.At(i);
|
field ^= array.At(i);
|
||||||
type = field.type();
|
type = field.type();
|
||||||
|
@ -2747,12 +2559,7 @@ void ClassFinalizer::CollectTypeArguments(
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (Isolate::Current()->error_on_bad_type()) {
|
// TODO(regis): Check if this is dead code.
|
||||||
const String& type_class_name = String::Handle(type_class.Name());
|
|
||||||
ReportError(cls, type.token_pos(),
|
|
||||||
"wrong number of type arguments for class '%s'",
|
|
||||||
type_class_name.ToCString());
|
|
||||||
}
|
|
||||||
// Discard provided type arguments and treat type as raw.
|
// Discard provided type arguments and treat type as raw.
|
||||||
}
|
}
|
||||||
// Fill arguments with type dynamic.
|
// Fill arguments with type dynamic.
|
||||||
|
@ -3216,9 +3023,6 @@ void ClassFinalizer::MarkTypeMalformed(const Error& prev_error,
|
||||||
LanguageError& error = LanguageError::Handle(LanguageError::NewFormattedV(
|
LanguageError& error = LanguageError::Handle(LanguageError::NewFormattedV(
|
||||||
prev_error, script, type.token_pos(), Report::AtLocation,
|
prev_error, script, type.token_pos(), Report::AtLocation,
|
||||||
Report::kMalformedType, Heap::kOld, format, args));
|
Report::kMalformedType, Heap::kOld, format, args));
|
||||||
if (Isolate::Current()->error_on_bad_type()) {
|
|
||||||
ReportError(error);
|
|
||||||
}
|
|
||||||
type.set_error(error);
|
type.set_error(error);
|
||||||
// Make the type raw, since it may not be possible to
|
// Make the type raw, since it may not be possible to
|
||||||
// properly finalize its type arguments.
|
// properly finalize its type arguments.
|
||||||
|
@ -3274,9 +3078,6 @@ void ClassFinalizer::FinalizeMalboundedType(const Error& prev_error,
|
||||||
prev_error, script, type.token_pos(), Report::AtLocation,
|
prev_error, script, type.token_pos(), Report::AtLocation,
|
||||||
Report::kMalboundedType, Heap::kOld, format, args));
|
Report::kMalboundedType, Heap::kOld, format, args));
|
||||||
va_end(args);
|
va_end(args);
|
||||||
if (Isolate::Current()->error_on_bad_type()) {
|
|
||||||
ReportError(error);
|
|
||||||
}
|
|
||||||
type.set_error(error);
|
type.set_error(error);
|
||||||
if (!type.IsFinalized()) {
|
if (!type.IsFinalized()) {
|
||||||
type.SetIsFinalized();
|
type.SetIsFinalized();
|
||||||
|
|
|
@ -152,10 +152,6 @@ class ClassFinalizer : public AllStatic {
|
||||||
static void CheckRecursiveType(const Class& cls,
|
static void CheckRecursiveType(const Class& cls,
|
||||||
const AbstractType& type,
|
const AbstractType& type,
|
||||||
PendingTypes* pending_types);
|
PendingTypes* pending_types);
|
||||||
static void CheckTypeBounds(const Class& cls, const AbstractType& type);
|
|
||||||
static void CheckTypeArgumentBounds(const Class& cls,
|
|
||||||
const TypeArguments& arguments,
|
|
||||||
Error* bound_error);
|
|
||||||
static void ResolveUpperBounds(const Class& cls);
|
static void ResolveUpperBounds(const Class& cls);
|
||||||
static void FinalizeUpperBounds(
|
static void FinalizeUpperBounds(
|
||||||
const Class& cls,
|
const Class& cls,
|
||||||
|
|
|
@ -1111,10 +1111,7 @@ void FlowGraph::PopulateEnvironmentFromFunctionEntry(
|
||||||
|
|
||||||
// Check if inlining_parameters include a type argument vector parameter.
|
// Check if inlining_parameters include a type argument vector parameter.
|
||||||
const intptr_t inlined_type_args_param =
|
const intptr_t inlined_type_args_param =
|
||||||
(FLAG_reify_generic_functions && (inlining_parameters != NULL) &&
|
((inlining_parameters != NULL) && function().IsGeneric()) ? 1 : 0;
|
||||||
function().IsGeneric())
|
|
||||||
? 1
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
for (intptr_t i = 0; i < parameter_count; i++) {
|
for (intptr_t i = 0; i < parameter_count; i++) {
|
||||||
ParameterInstr* param = new (zone()) ParameterInstr(i, function_entry);
|
ParameterInstr* param = new (zone()) ParameterInstr(i, function_entry);
|
||||||
|
@ -1139,11 +1136,9 @@ void FlowGraph::PopulateEnvironmentFromFunctionEntry(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace the type arguments slot with a special parameter.
|
// Replace the type arguments slot with a special parameter.
|
||||||
const bool reify_generic_argument =
|
const bool reify_generic_argument = function().IsGeneric();
|
||||||
function().IsGeneric() && FLAG_reify_generic_functions;
|
|
||||||
if (reify_generic_argument) {
|
if (reify_generic_argument) {
|
||||||
ASSERT(parsed_function().function_type_arguments() != NULL);
|
ASSERT(parsed_function().function_type_arguments() != NULL);
|
||||||
|
|
||||||
Definition* defn;
|
Definition* defn;
|
||||||
if (inlining_parameters == NULL) {
|
if (inlining_parameters == NULL) {
|
||||||
// Note: If we are not inlining, then the prologue builder will
|
// Note: If we are not inlining, then the prologue builder will
|
||||||
|
|
|
@ -492,7 +492,7 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest(
|
||||||
}
|
}
|
||||||
if (type.IsType()) {
|
if (type.IsType()) {
|
||||||
// Smi is FutureOr<T>, when T is a top type or int or num.
|
// Smi is FutureOr<T>, when T is a top type or int or num.
|
||||||
if (!FLAG_strong || !Class::Handle(type.type_class()).IsFutureOrClass()) {
|
if (!Class::Handle(type.type_class()).IsFutureOrClass()) {
|
||||||
__ BranchIfSmi(kInstanceReg, is_not_instance_lbl);
|
__ BranchIfSmi(kInstanceReg, is_not_instance_lbl);
|
||||||
}
|
}
|
||||||
__ ldm(IA, SP,
|
__ ldm(IA, SP,
|
||||||
|
@ -1154,8 +1154,7 @@ void FlowGraphCompiler::EmitOptimizedStaticCall(
|
||||||
LocationSummary* locs,
|
LocationSummary* locs,
|
||||||
Code::EntryKind entry_kind) {
|
Code::EntryKind entry_kind) {
|
||||||
ASSERT(!function.IsClosureFunction());
|
ASSERT(!function.IsClosureFunction());
|
||||||
if (function.HasOptionalParameters() ||
|
if (function.HasOptionalParameters() || function.IsGeneric()) {
|
||||||
(FLAG_reify_generic_functions && function.IsGeneric())) {
|
|
||||||
__ LoadObject(R4, arguments_descriptor);
|
__ LoadObject(R4, arguments_descriptor);
|
||||||
} else {
|
} else {
|
||||||
__ LoadImmediate(R4, 0); // GC safe smi zero because of stub.
|
__ LoadImmediate(R4, 0); // GC safe smi zero because of stub.
|
||||||
|
|
|
@ -478,7 +478,7 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest(
|
||||||
}
|
}
|
||||||
if (type.IsType()) {
|
if (type.IsType()) {
|
||||||
// Smi is FutureOr<T>, when T is a top type or int or num.
|
// Smi is FutureOr<T>, when T is a top type or int or num.
|
||||||
if (!FLAG_strong || !Class::Handle(type.type_class()).IsFutureOrClass()) {
|
if (!Class::Handle(type.type_class()).IsFutureOrClass()) {
|
||||||
__ BranchIfSmi(kInstanceReg, is_not_instance_lbl);
|
__ BranchIfSmi(kInstanceReg, is_not_instance_lbl);
|
||||||
}
|
}
|
||||||
__ ldp(kFunctionTypeArgumentsReg, kInstantiatorTypeArgumentsReg,
|
__ ldp(kFunctionTypeArgumentsReg, kInstantiatorTypeArgumentsReg,
|
||||||
|
@ -1136,8 +1136,7 @@ void FlowGraphCompiler::EmitOptimizedStaticCall(
|
||||||
Code::EntryKind entry_kind) {
|
Code::EntryKind entry_kind) {
|
||||||
// TODO(sjindel/entrypoints): Support multiple entrypoints on ARM64.
|
// TODO(sjindel/entrypoints): Support multiple entrypoints on ARM64.
|
||||||
ASSERT(!function.IsClosureFunction());
|
ASSERT(!function.IsClosureFunction());
|
||||||
if (function.HasOptionalParameters() ||
|
if (function.HasOptionalParameters() || function.IsGeneric()) {
|
||||||
(FLAG_reify_generic_functions && function.IsGeneric())) {
|
|
||||||
__ LoadObject(R4, arguments_descriptor);
|
__ LoadObject(R4, arguments_descriptor);
|
||||||
} else {
|
} else {
|
||||||
__ LoadImmediate(R4, 0); // GC safe smi zero because of stub.
|
__ LoadImmediate(R4, 0); // GC safe smi zero because of stub.
|
||||||
|
|
|
@ -498,7 +498,7 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest(
|
||||||
}
|
}
|
||||||
if (type.IsType()) {
|
if (type.IsType()) {
|
||||||
// Smi is FutureOr<T>, when T is a top type or int or num.
|
// Smi is FutureOr<T>, when T is a top type or int or num.
|
||||||
if (!FLAG_strong || !Class::Handle(type.type_class()).IsFutureOrClass()) {
|
if (!Class::Handle(type.type_class()).IsFutureOrClass()) {
|
||||||
__ testl(kInstanceReg, Immediate(kSmiTagMask)); // Is instance Smi?
|
__ testl(kInstanceReg, Immediate(kSmiTagMask)); // Is instance Smi?
|
||||||
__ j(ZERO, is_not_instance_lbl);
|
__ j(ZERO, is_not_instance_lbl);
|
||||||
}
|
}
|
||||||
|
@ -1008,8 +1008,7 @@ void FlowGraphCompiler::EmitOptimizedStaticCall(
|
||||||
LocationSummary* locs,
|
LocationSummary* locs,
|
||||||
Code::EntryKind entry_kind) {
|
Code::EntryKind entry_kind) {
|
||||||
// TODO(sjindel/entrypoints): Support multiple entrypoints on IA32.
|
// TODO(sjindel/entrypoints): Support multiple entrypoints on IA32.
|
||||||
if (function.HasOptionalParameters() ||
|
if (function.HasOptionalParameters() || function.IsGeneric()) {
|
||||||
(FLAG_reify_generic_functions && function.IsGeneric())) {
|
|
||||||
__ LoadObject(EDX, arguments_descriptor);
|
__ LoadObject(EDX, arguments_descriptor);
|
||||||
} else {
|
} else {
|
||||||
__ xorl(EDX, EDX); // GC safe smi zero because of stub.
|
__ xorl(EDX, EDX); // GC safe smi zero because of stub.
|
||||||
|
|
|
@ -504,7 +504,7 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest(
|
||||||
}
|
}
|
||||||
if (type.IsType()) {
|
if (type.IsType()) {
|
||||||
// Smi is FutureOr<T>, when T is a top type or int or num.
|
// Smi is FutureOr<T>, when T is a top type or int or num.
|
||||||
if (!FLAG_strong || !Class::Handle(type.type_class()).IsFutureOrClass()) {
|
if (!Class::Handle(type.type_class()).IsFutureOrClass()) {
|
||||||
__ testq(kInstanceReg, Immediate(kSmiTagMask)); // Is instance Smi?
|
__ testq(kInstanceReg, Immediate(kSmiTagMask)); // Is instance Smi?
|
||||||
__ j(ZERO, is_not_instance_lbl);
|
__ j(ZERO, is_not_instance_lbl);
|
||||||
}
|
}
|
||||||
|
@ -1131,8 +1131,7 @@ void FlowGraphCompiler::EmitOptimizedStaticCall(
|
||||||
LocationSummary* locs,
|
LocationSummary* locs,
|
||||||
Code::EntryKind entry_kind) {
|
Code::EntryKind entry_kind) {
|
||||||
ASSERT(!function.IsClosureFunction());
|
ASSERT(!function.IsClosureFunction());
|
||||||
if (function.HasOptionalParameters() ||
|
if (function.HasOptionalParameters() || function.IsGeneric()) {
|
||||||
(FLAG_reify_generic_functions && function.IsGeneric())) {
|
|
||||||
__ LoadObject(R10, arguments_descriptor);
|
__ LoadObject(R10, arguments_descriptor);
|
||||||
} else {
|
} else {
|
||||||
__ xorl(R10, R10); // GC safe smi zero because of stub.
|
__ xorl(R10, R10); // GC safe smi zero because of stub.
|
||||||
|
|
|
@ -2675,7 +2675,7 @@ Definition* AssertBooleanInstr::Canonicalize(FlowGraph* flow_graph) {
|
||||||
|
|
||||||
// In strong mode type is already verified either by static analysis
|
// In strong mode type is already verified either by static analysis
|
||||||
// or runtime checks, so AssertBoolean just ensures that value is not null.
|
// or runtime checks, so AssertBoolean just ensures that value is not null.
|
||||||
if (FLAG_strong && !value()->Type()->is_nullable()) {
|
if (!value()->Type()->is_nullable()) {
|
||||||
return value()->definition();
|
return value()->definition();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2781,7 +2781,7 @@ Definition* AssertAssignableInstr::Canonicalize(FlowGraph* flow_graph) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Definition* InstantiateTypeArgumentsInstr::Canonicalize(FlowGraph* flow_graph) {
|
Definition* InstantiateTypeArgumentsInstr::Canonicalize(FlowGraph* flow_graph) {
|
||||||
return (Isolate::Current()->type_checks() || HasUses()) ? this : NULL;
|
return HasUses() ? this : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
LocationSummary* DebugStepCheckInstr::MakeLocationSummary(Zone* zone,
|
LocationSummary* DebugStepCheckInstr::MakeLocationSummary(Zone* zone,
|
||||||
|
|
|
@ -2929,7 +2929,7 @@ class AssertAssignableInstr : public TemplateDefinition<3, Throws, Pure> {
|
||||||
ASSERT(!dst_type.IsNull());
|
ASSERT(!dst_type.IsNull());
|
||||||
ASSERT(!dst_type.IsTypeRef());
|
ASSERT(!dst_type.IsTypeRef());
|
||||||
ASSERT(!dst_name.IsNull());
|
ASSERT(!dst_name.IsNull());
|
||||||
ASSERT(!FLAG_strong || !dst_type.IsDynamicType());
|
ASSERT(!dst_type.IsDynamicType());
|
||||||
SetInputAt(0, value);
|
SetInputAt(0, value);
|
||||||
SetInputAt(1, instantiator_type_arguments);
|
SetInputAt(1, instantiator_type_arguments);
|
||||||
SetInputAt(2, function_type_arguments);
|
SetInputAt(2, function_type_arguments);
|
||||||
|
@ -4215,13 +4215,6 @@ class StoreInstanceFieldInstr : public TemplateDefinition<2, NoThrow> {
|
||||||
intptr_t OffsetInBytes() const { return slot().offset_in_bytes(); }
|
intptr_t OffsetInBytes() const { return slot().offset_in_bytes(); }
|
||||||
|
|
||||||
Assembler::CanBeSmi CanValueBeSmi() const {
|
Assembler::CanBeSmi CanValueBeSmi() const {
|
||||||
Isolate* isolate = Isolate::Current();
|
|
||||||
if (isolate->type_checks() && !FLAG_strong) {
|
|
||||||
// Dart 1 sometimes places a store into a context before a parameter
|
|
||||||
// type check.
|
|
||||||
return Assembler::kValueCanBeSmi;
|
|
||||||
}
|
|
||||||
|
|
||||||
const intptr_t cid = value()->Type()->ToNullableCid();
|
const intptr_t cid = value()->Type()->ToNullableCid();
|
||||||
// Write barrier is skipped for nullable and non-nullable smis.
|
// Write barrier is skipped for nullable and non-nullable smis.
|
||||||
ASSERT(cid != kSmiCid);
|
ASSERT(cid != kSmiCid);
|
||||||
|
@ -4387,13 +4380,6 @@ class StoreStaticFieldInstr : public TemplateDefinition<1, NoThrow> {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Assembler::CanBeSmi CanValueBeSmi() const {
|
Assembler::CanBeSmi CanValueBeSmi() const {
|
||||||
Isolate* isolate = Isolate::Current();
|
|
||||||
if (isolate->type_checks() && !FLAG_strong) {
|
|
||||||
// Dart 1 sometimes places a store into a context before a parameter
|
|
||||||
// type check.
|
|
||||||
return Assembler::kValueCanBeSmi;
|
|
||||||
}
|
|
||||||
|
|
||||||
const intptr_t cid = value()->Type()->ToNullableCid();
|
const intptr_t cid = value()->Type()->ToNullableCid();
|
||||||
// Write barrier is skipped for nullable and non-nullable smis.
|
// Write barrier is skipped for nullable and non-nullable smis.
|
||||||
ASSERT(cid != kSmiCid);
|
ASSERT(cid != kSmiCid);
|
||||||
|
|
|
@ -492,18 +492,9 @@ static void EmitAssertBoolean(Register reg,
|
||||||
// Call the runtime if the object is not bool::true or bool::false.
|
// Call the runtime if the object is not bool::true or bool::false.
|
||||||
ASSERT(locs->always_calls());
|
ASSERT(locs->always_calls());
|
||||||
Label done;
|
Label done;
|
||||||
Isolate* isolate = Isolate::Current();
|
|
||||||
|
|
||||||
if (isolate->type_checks()) {
|
__ CompareObject(reg, Object::null_instance());
|
||||||
__ CompareObject(reg, Bool::True());
|
__ b(&done, NE);
|
||||||
__ b(&done, EQ);
|
|
||||||
__ CompareObject(reg, Bool::False());
|
|
||||||
__ b(&done, EQ);
|
|
||||||
} else {
|
|
||||||
ASSERT(isolate->asserts() || FLAG_strong);
|
|
||||||
__ CompareObject(reg, Object::null_instance());
|
|
||||||
__ b(&done, NE);
|
|
||||||
}
|
|
||||||
|
|
||||||
__ Push(reg); // Push the source object.
|
__ Push(reg); // Push the source object.
|
||||||
compiler->GenerateRuntimeCall(token_pos, deopt_id,
|
compiler->GenerateRuntimeCall(token_pos, deopt_id,
|
||||||
|
@ -937,10 +928,7 @@ void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||||
|
|
||||||
// All arguments are already @SP due to preceding PushArgument()s.
|
// All arguments are already @SP due to preceding PushArgument()s.
|
||||||
ASSERT(ArgumentCount() ==
|
ASSERT(ArgumentCount() ==
|
||||||
function().NumParameters() +
|
function().NumParameters() + (function().IsGeneric() ? 1 : 0));
|
||||||
(function().IsGeneric() && FLAG_reify_generic_functions)
|
|
||||||
? 1
|
|
||||||
: 0);
|
|
||||||
|
|
||||||
// Push the result place holder initialized to NULL.
|
// Push the result place holder initialized to NULL.
|
||||||
__ PushObject(Object::null_object());
|
__ PushObject(Object::null_object());
|
||||||
|
|
|
@ -491,18 +491,9 @@ static void EmitAssertBoolean(Register reg,
|
||||||
// Call the runtime if the object is not bool::true or bool::false.
|
// Call the runtime if the object is not bool::true or bool::false.
|
||||||
ASSERT(locs->always_calls());
|
ASSERT(locs->always_calls());
|
||||||
Label done;
|
Label done;
|
||||||
Isolate* isolate = Isolate::Current();
|
|
||||||
|
|
||||||
if (isolate->type_checks()) {
|
__ CompareObject(reg, Object::null_instance());
|
||||||
__ CompareObject(reg, Bool::True());
|
__ b(&done, NE);
|
||||||
__ b(&done, EQ);
|
|
||||||
__ CompareObject(reg, Bool::False());
|
|
||||||
__ b(&done, EQ);
|
|
||||||
} else {
|
|
||||||
ASSERT(isolate->asserts() || FLAG_strong);
|
|
||||||
__ CompareObject(reg, Object::null_instance());
|
|
||||||
__ b(&done, NE);
|
|
||||||
}
|
|
||||||
|
|
||||||
__ Push(reg); // Push the source object.
|
__ Push(reg); // Push the source object.
|
||||||
compiler->GenerateRuntimeCall(token_pos, deopt_id,
|
compiler->GenerateRuntimeCall(token_pos, deopt_id,
|
||||||
|
@ -827,10 +818,7 @@ void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||||
|
|
||||||
// All arguments are already @SP due to preceding PushArgument()s.
|
// All arguments are already @SP due to preceding PushArgument()s.
|
||||||
ASSERT(ArgumentCount() ==
|
ASSERT(ArgumentCount() ==
|
||||||
function().NumParameters() +
|
function().NumParameters() + (function().IsGeneric() ? 1 : 0));
|
||||||
(function().IsGeneric() && FLAG_reify_generic_functions)
|
|
||||||
? 1
|
|
||||||
: 0);
|
|
||||||
|
|
||||||
// Push the result place holder initialized to NULL.
|
// Push the result place holder initialized to NULL.
|
||||||
__ PushObject(Object::null_object());
|
__ PushObject(Object::null_object());
|
||||||
|
|
|
@ -199,8 +199,7 @@ EMIT_NATIVE_CODE(AssertBoolean,
|
||||||
if (compiler->is_optimizing()) {
|
if (compiler->is_optimizing()) {
|
||||||
__ Push(locs()->in(0).reg());
|
__ Push(locs()->in(0).reg());
|
||||||
}
|
}
|
||||||
Isolate* isolate = Isolate::Current();
|
__ AssertBoolean(0);
|
||||||
__ AssertBoolean(isolate->type_checks() ? 1 : 0);
|
|
||||||
compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
|
compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
|
||||||
token_pos());
|
token_pos());
|
||||||
compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
|
compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
|
||||||
|
|
|
@ -312,18 +312,9 @@ static void EmitAssertBoolean(Register reg,
|
||||||
// Call the runtime if the object is not bool::true or bool::false.
|
// Call the runtime if the object is not bool::true or bool::false.
|
||||||
ASSERT(locs->always_calls());
|
ASSERT(locs->always_calls());
|
||||||
Label done;
|
Label done;
|
||||||
Isolate* isolate = Isolate::Current();
|
|
||||||
|
|
||||||
if (isolate->type_checks()) {
|
__ CompareObject(reg, Object::null_instance());
|
||||||
__ CompareObject(reg, Bool::True());
|
__ j(NOT_EQUAL, &done, Assembler::kNearJump);
|
||||||
__ j(EQUAL, &done, Assembler::kNearJump);
|
|
||||||
__ CompareObject(reg, Bool::False());
|
|
||||||
__ j(EQUAL, &done, Assembler::kNearJump);
|
|
||||||
} else {
|
|
||||||
ASSERT(isolate->asserts() || FLAG_strong);
|
|
||||||
__ CompareObject(reg, Object::null_instance());
|
|
||||||
__ j(NOT_EQUAL, &done, Assembler::kNearJump);
|
|
||||||
}
|
|
||||||
|
|
||||||
__ pushl(reg); // Push the source object.
|
__ pushl(reg); // Push the source object.
|
||||||
compiler->GenerateRuntimeCall(token_pos, deopt_id,
|
compiler->GenerateRuntimeCall(token_pos, deopt_id,
|
||||||
|
@ -822,10 +813,7 @@ void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||||
|
|
||||||
// All arguments are already @ESP due to preceding PushArgument()s.
|
// All arguments are already @ESP due to preceding PushArgument()s.
|
||||||
ASSERT(ArgumentCount() ==
|
ASSERT(ArgumentCount() ==
|
||||||
function().NumParameters() +
|
function().NumParameters() + (function().IsGeneric() ? 1 : 0));
|
||||||
(function().IsGeneric() && FLAG_reify_generic_functions)
|
|
||||||
? 1
|
|
||||||
: 0);
|
|
||||||
|
|
||||||
// Push the result place holder initialized to NULL.
|
// Push the result place holder initialized to NULL.
|
||||||
__ PushObject(Object::null_object());
|
__ PushObject(Object::null_object());
|
||||||
|
|
|
@ -466,18 +466,9 @@ static void EmitAssertBoolean(Register reg,
|
||||||
// Call the runtime if the object is not bool::true or bool::false.
|
// Call the runtime if the object is not bool::true or bool::false.
|
||||||
ASSERT(locs->always_calls());
|
ASSERT(locs->always_calls());
|
||||||
Label done;
|
Label done;
|
||||||
Isolate* isolate = Isolate::Current();
|
|
||||||
|
|
||||||
if (isolate->type_checks()) {
|
__ CompareObject(reg, Object::null_instance());
|
||||||
__ CompareObject(reg, Bool::True());
|
__ j(NOT_EQUAL, &done, Assembler::kNearJump);
|
||||||
__ j(EQUAL, &done, Assembler::kNearJump);
|
|
||||||
__ CompareObject(reg, Bool::False());
|
|
||||||
__ j(EQUAL, &done, Assembler::kNearJump);
|
|
||||||
} else {
|
|
||||||
ASSERT(isolate->asserts() || FLAG_strong);
|
|
||||||
__ CompareObject(reg, Object::null_instance());
|
|
||||||
__ j(NOT_EQUAL, &done, Assembler::kNearJump);
|
|
||||||
}
|
|
||||||
|
|
||||||
__ pushq(reg); // Push the source object.
|
__ pushq(reg); // Push the source object.
|
||||||
compiler->GenerateRuntimeCall(token_pos, deopt_id,
|
compiler->GenerateRuntimeCall(token_pos, deopt_id,
|
||||||
|
@ -849,10 +840,7 @@ void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||||
|
|
||||||
// All arguments are already @RSP due to preceding PushArgument()s.
|
// All arguments are already @RSP due to preceding PushArgument()s.
|
||||||
ASSERT(ArgumentCount() ==
|
ASSERT(ArgumentCount() ==
|
||||||
function().NumParameters() +
|
function().NumParameters() + (function().IsGeneric() ? 1 : 0));
|
||||||
(function().IsGeneric() && FLAG_reify_generic_functions)
|
|
||||||
? 1
|
|
||||||
: 0);
|
|
||||||
|
|
||||||
// Push the result place holder initialized to NULL.
|
// Push the result place holder initialized to NULL.
|
||||||
__ PushObject(Object::null_object());
|
__ PushObject(Object::null_object());
|
||||||
|
|
|
@ -1049,8 +1049,7 @@ class CallSiteInliner : public ValueObject {
|
||||||
// without linking between the caller and callee graphs.
|
// without linking between the caller and callee graphs.
|
||||||
// TODO(zerny): Put more information in the stubs, eg, type information.
|
// TODO(zerny): Put more information in the stubs, eg, type information.
|
||||||
const intptr_t first_actual_param_index = call_data->first_arg_index;
|
const intptr_t first_actual_param_index = call_data->first_arg_index;
|
||||||
const intptr_t inlined_type_args_param =
|
const intptr_t inlined_type_args_param = function.IsGeneric() ? 1 : 0;
|
||||||
(FLAG_reify_generic_functions && function.IsGeneric()) ? 1 : 0;
|
|
||||||
const intptr_t num_inlined_params =
|
const intptr_t num_inlined_params =
|
||||||
inlined_type_args_param + function.NumParameters();
|
inlined_type_args_param + function.NumParameters();
|
||||||
ZoneGrowableArray<Definition*>* param_stubs =
|
ZoneGrowableArray<Definition*>* param_stubs =
|
||||||
|
@ -3028,7 +3027,6 @@ static bool InlineByteArrayBaseStore(FlowGraph* flow_graph,
|
||||||
cursor =
|
cursor =
|
||||||
flow_graph->AppendTo(cursor, check, call->env(), FlowGraph::kEffect);
|
flow_graph->AppendTo(cursor, check, call->env(), FlowGraph::kEffect);
|
||||||
// With an explicit null check, a non-speculative unbox suffices.
|
// With an explicit null check, a non-speculative unbox suffices.
|
||||||
ASSERT(FLAG_strong);
|
|
||||||
switch (view_cid) {
|
switch (view_cid) {
|
||||||
case kTypedDataFloat32ArrayCid:
|
case kTypedDataFloat32ArrayCid:
|
||||||
case kTypedDataFloat64ArrayCid:
|
case kTypedDataFloat64ArrayCid:
|
||||||
|
|
|
@ -761,11 +761,7 @@ const AbstractType* CompileType::ToAbstractType() {
|
||||||
Isolate* I = Isolate::Current();
|
Isolate* I = Isolate::Current();
|
||||||
const Class& type_class = Class::Handle(I->class_table()->At(cid_));
|
const Class& type_class = Class::Handle(I->class_table()->At(cid_));
|
||||||
if (type_class.NumTypeArguments() > 0) {
|
if (type_class.NumTypeArguments() > 0) {
|
||||||
if (FLAG_strong) {
|
type_ = &AbstractType::ZoneHandle(type_class.RareType());
|
||||||
type_ = &AbstractType::ZoneHandle(type_class.RareType());
|
|
||||||
} else {
|
|
||||||
type_ = &Object::dynamic_type();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
type_ = &Type::ZoneHandle(Type::NewNonParameterizedType(type_class));
|
type_ = &Type::ZoneHandle(Type::NewNonParameterizedType(type_class));
|
||||||
}
|
}
|
||||||
|
@ -1215,8 +1211,7 @@ CompileType StaticCallInstr::ComputeType() const {
|
||||||
return CompileType::FromCid(MethodRecognizer::ResultCid(function_));
|
return CompileType::FromCid(MethodRecognizer::ResultCid(function_));
|
||||||
}
|
}
|
||||||
|
|
||||||
const Isolate* isolate = Isolate::Current();
|
if (Isolate::Current()->can_use_strong_mode_types()) {
|
||||||
if (isolate->can_use_strong_mode_types() || isolate->type_checks()) {
|
|
||||||
const AbstractType& result_type =
|
const AbstractType& result_type =
|
||||||
AbstractType::ZoneHandle(function().result_type());
|
AbstractType::ZoneHandle(function().result_type());
|
||||||
// TODO(dartbug.com/30480): instantiate generic result_type if possible.
|
// TODO(dartbug.com/30480): instantiate generic result_type if possible.
|
||||||
|
@ -1234,8 +1229,7 @@ CompileType StaticCallInstr::ComputeType() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
CompileType LoadLocalInstr::ComputeType() const {
|
CompileType LoadLocalInstr::ComputeType() const {
|
||||||
const Isolate* isolate = Isolate::Current();
|
if (Isolate::Current()->can_use_strong_mode_types()) {
|
||||||
if (isolate->can_use_strong_mode_types() || isolate->type_checks()) {
|
|
||||||
const AbstractType& local_type = local().type();
|
const AbstractType& local_type = local().type();
|
||||||
TraceStrongModeType(this, local_type);
|
TraceStrongModeType(this, local_type);
|
||||||
return CompileType::FromAbstractType(local_type);
|
return CompileType::FromAbstractType(local_type);
|
||||||
|
@ -1270,8 +1264,7 @@ CompileType LoadStaticFieldInstr::ComputeType() const {
|
||||||
intptr_t cid = kDynamicCid;
|
intptr_t cid = kDynamicCid;
|
||||||
AbstractType* abstract_type = NULL;
|
AbstractType* abstract_type = NULL;
|
||||||
const Field& field = this->StaticField();
|
const Field& field = this->StaticField();
|
||||||
const Isolate* isolate = Isolate::Current();
|
if (Isolate::Current()->can_use_strong_mode_types()) {
|
||||||
if (isolate->can_use_strong_mode_types() || isolate->type_checks()) {
|
|
||||||
cid = kIllegalCid; // Abstract type is known, calculate cid lazily.
|
cid = kIllegalCid; // Abstract type is known, calculate cid lazily.
|
||||||
abstract_type = &AbstractType::ZoneHandle(field.type());
|
abstract_type = &AbstractType::ZoneHandle(field.type());
|
||||||
TraceStrongModeType(this, *abstract_type);
|
TraceStrongModeType(this, *abstract_type);
|
||||||
|
@ -1329,8 +1322,7 @@ CompileType LoadFieldInstr::ComputeType() const {
|
||||||
intptr_t cid = kDynamicCid;
|
intptr_t cid = kDynamicCid;
|
||||||
const AbstractType* abstract_type = NULL;
|
const AbstractType* abstract_type = NULL;
|
||||||
if (isolate->can_use_strong_mode_types() ||
|
if (isolate->can_use_strong_mode_types() ||
|
||||||
(isolate->type_checks() &&
|
(field_type.IsFunctionType() || field_type.HasTypeClass())) {
|
||||||
(field_type.IsFunctionType() || field_type.HasTypeClass()))) {
|
|
||||||
cid = kIllegalCid; // Abstract type is known, calculate cid lazily.
|
cid = kIllegalCid; // Abstract type is known, calculate cid lazily.
|
||||||
abstract_type = &field_type;
|
abstract_type = &field_type;
|
||||||
TraceStrongModeType(this, *abstract_type);
|
TraceStrongModeType(this, *abstract_type);
|
||||||
|
|
|
@ -1001,8 +1001,7 @@ bool CallSpecializer::TryInlineInstanceSetter(InstanceCallInstr* instr,
|
||||||
// Compute if we need to type check the value. Always type check if
|
// Compute if we need to type check the value. Always type check if
|
||||||
// not in strong mode or if at a dynamic invocation.
|
// not in strong mode or if at a dynamic invocation.
|
||||||
bool needs_check = true;
|
bool needs_check = true;
|
||||||
if (FLAG_strong && !instr->interface_target().IsNull() &&
|
if (!instr->interface_target().IsNull() && (field.kernel_offset() >= 0)) {
|
||||||
(field.kernel_offset() >= 0)) {
|
|
||||||
bool is_covariant = false;
|
bool is_covariant = false;
|
||||||
bool is_generic_covariant = false;
|
bool is_generic_covariant = false;
|
||||||
field.GetCovarianceAttributes(&is_covariant, &is_generic_covariant);
|
field.GetCovarianceAttributes(&is_covariant, &is_generic_covariant);
|
||||||
|
|
|
@ -872,7 +872,7 @@ const Object& ConstantEvaluator::RunFunction(TokenPosition position,
|
||||||
// We use a kernel2kernel constant evaluator in Dart 2.0 AOT compilation, so
|
// We use a kernel2kernel constant evaluator in Dart 2.0 AOT compilation, so
|
||||||
// we should never end up evaluating constants using the VM's constant
|
// we should never end up evaluating constants using the VM's constant
|
||||||
// evaluator.
|
// evaluator.
|
||||||
if (FLAG_strong && FLAG_precompiled_mode) {
|
if (FLAG_precompiled_mode) {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -954,7 +954,7 @@ RawObject* ConstantEvaluator::EvaluateConstConstructorCall(
|
||||||
// We use a kernel2kernel constant evaluator in Dart 2.0 AOT compilation, so
|
// We use a kernel2kernel constant evaluator in Dart 2.0 AOT compilation, so
|
||||||
// we should never end up evaluating constants using the VM's constant
|
// we should never end up evaluating constants using the VM's constant
|
||||||
// evaluator.
|
// evaluator.
|
||||||
if (FLAG_strong && FLAG_precompiled_mode) {
|
if (FLAG_precompiled_mode) {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -432,7 +432,7 @@ Fragment StreamingFlowGraphBuilder::BuildInitializers(
|
||||||
Fragment StreamingFlowGraphBuilder::BuildDefaultTypeHandling(
|
Fragment StreamingFlowGraphBuilder::BuildDefaultTypeHandling(
|
||||||
const Function& function,
|
const Function& function,
|
||||||
intptr_t type_parameters_offset) {
|
intptr_t type_parameters_offset) {
|
||||||
if (function.IsGeneric() && FLAG_reify_generic_functions) {
|
if (function.IsGeneric()) {
|
||||||
AlternativeReadingScope alt(&reader_);
|
AlternativeReadingScope alt(&reader_);
|
||||||
SetOffset(type_parameters_offset);
|
SetOffset(type_parameters_offset);
|
||||||
intptr_t num_type_params = ReadListLength();
|
intptr_t num_type_params = ReadListLength();
|
||||||
|
@ -554,7 +554,7 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfImplicitClosureFunction(
|
||||||
FunctionNodeHelper::kPositionalParameters);
|
FunctionNodeHelper::kPositionalParameters);
|
||||||
|
|
||||||
intptr_t type_args_len = 0;
|
intptr_t type_args_len = 0;
|
||||||
if (function.IsGeneric() && FLAG_reify_generic_functions) {
|
if (function.IsGeneric()) {
|
||||||
type_args_len = function.NumTypeParameters();
|
type_args_len = function.NumTypeParameters();
|
||||||
ASSERT(parsed_function()->function_type_arguments() != NULL);
|
ASSERT(parsed_function()->function_type_arguments() != NULL);
|
||||||
body += LoadLocal(parsed_function()->function_type_arguments());
|
body += LoadLocal(parsed_function()->function_type_arguments());
|
||||||
|
@ -720,7 +720,7 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfNoSuchMethodForwarder(
|
||||||
body += IntConstant(0);
|
body += IntConstant(0);
|
||||||
body += StoreLocal(TokenPosition::kNoSource, argument_count_var);
|
body += StoreLocal(TokenPosition::kNoSource, argument_count_var);
|
||||||
body += Drop();
|
body += Drop();
|
||||||
if (function.IsGeneric() && FLAG_reify_generic_functions) {
|
if (function.IsGeneric()) {
|
||||||
Fragment then;
|
Fragment then;
|
||||||
Fragment otherwise;
|
Fragment otherwise;
|
||||||
otherwise += IntConstant(1);
|
otherwise += IntConstant(1);
|
||||||
|
@ -769,7 +769,7 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfNoSuchMethodForwarder(
|
||||||
// arguments[0] = function_type_arguments;
|
// arguments[0] = function_type_arguments;
|
||||||
// i = 1;
|
// i = 1;
|
||||||
// }
|
// }
|
||||||
if (function.IsGeneric() && FLAG_reify_generic_functions) {
|
if (function.IsGeneric()) {
|
||||||
Fragment store;
|
Fragment store;
|
||||||
store += LoadLocal(arguments);
|
store += LoadLocal(arguments);
|
||||||
store += IntConstant(0);
|
store += IntConstant(0);
|
||||||
|
@ -983,9 +983,6 @@ void StreamingFlowGraphBuilder::BuildArgumentTypeChecks(
|
||||||
ASSERT(forwarding_params.Length() == num_type_params);
|
ASSERT(forwarding_params.Length() == num_type_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool has_reified_type_arguments =
|
|
||||||
FLAG_strong && FLAG_reify_generic_functions;
|
|
||||||
|
|
||||||
TypeParameter& forwarding_param = TypeParameter::Handle(Z);
|
TypeParameter& forwarding_param = TypeParameter::Handle(Z);
|
||||||
Fragment check_bounds;
|
Fragment check_bounds;
|
||||||
for (intptr_t i = 0; i < num_type_params; ++i) {
|
for (intptr_t i = 0; i < num_type_params; ++i) {
|
||||||
|
@ -995,10 +992,6 @@ void StreamingFlowGraphBuilder::BuildArgumentTypeChecks(
|
||||||
AbstractType& bound = T.BuildType(); // read bound
|
AbstractType& bound = T.BuildType(); // read bound
|
||||||
helper.Finish();
|
helper.Finish();
|
||||||
|
|
||||||
if (!has_reified_type_arguments) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (forwarding_target != NULL) {
|
if (forwarding_target != NULL) {
|
||||||
forwarding_param ^= forwarding_params.TypeAt(i);
|
forwarding_param ^= forwarding_params.TypeAt(i);
|
||||||
bound = forwarding_param.bound();
|
bound = forwarding_param.bound();
|
||||||
|
@ -1137,8 +1130,6 @@ void StreamingFlowGraphBuilder::BuildArgumentTypeChecks(
|
||||||
}
|
}
|
||||||
|
|
||||||
Fragment StreamingFlowGraphBuilder::PushAllArguments(PushedArguments* pushed) {
|
Fragment StreamingFlowGraphBuilder::PushAllArguments(PushedArguments* pushed) {
|
||||||
ASSERT(FLAG_strong);
|
|
||||||
|
|
||||||
FunctionNodeHelper function_node_helper(this);
|
FunctionNodeHelper function_node_helper(this);
|
||||||
function_node_helper.SetNext(FunctionNodeHelper::kTypeParameters);
|
function_node_helper.SetNext(FunctionNodeHelper::kTypeParameters);
|
||||||
|
|
||||||
|
@ -1152,11 +1143,9 @@ Fragment StreamingFlowGraphBuilder::PushAllArguments(PushedArguments* pushed) {
|
||||||
helper.Finish();
|
helper.Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FLAG_reify_generic_functions) {
|
body += LoadLocal(parsed_function()->function_type_arguments());
|
||||||
body += LoadLocal(parsed_function()->function_type_arguments());
|
body += PushArgument();
|
||||||
body += PushArgument();
|
pushed->type_args_len = num_type_params;
|
||||||
pushed->type_args_len = num_type_params;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
function_node_helper.SetJustRead(FunctionNodeHelper::kTypeParameters);
|
function_node_helper.SetJustRead(FunctionNodeHelper::kTypeParameters);
|
||||||
function_node_helper.ReadUntilExcluding(
|
function_node_helper.ReadUntilExcluding(
|
||||||
|
@ -1360,8 +1349,7 @@ Fragment StreamingFlowGraphBuilder::TypeArgumentsHandling(
|
||||||
BuildDefaultTypeHandling(dart_function, type_parameters_offset);
|
BuildDefaultTypeHandling(dart_function, type_parameters_offset);
|
||||||
|
|
||||||
if (dart_function.IsClosureFunction() &&
|
if (dart_function.IsClosureFunction() &&
|
||||||
dart_function.NumParentTypeParameters() > 0 &&
|
dart_function.NumParentTypeParameters() > 0) {
|
||||||
FLAG_reify_generic_functions) {
|
|
||||||
LocalVariable* closure =
|
LocalVariable* closure =
|
||||||
parsed_function()->node_sequence()->scope()->VariableAt(0);
|
parsed_function()->node_sequence()->scope()->VariableAt(0);
|
||||||
|
|
||||||
|
@ -2749,15 +2737,6 @@ Fragment StreamingFlowGraphBuilder::CheckBoolean(TokenPosition position) {
|
||||||
return flow_graph_builder_->CheckBoolean(position);
|
return flow_graph_builder_->CheckBoolean(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fragment StreamingFlowGraphBuilder::CheckAssignableInCheckedMode(
|
|
||||||
const AbstractType& dst_type,
|
|
||||||
const String& dst_name) {
|
|
||||||
if (I->type_checks()) {
|
|
||||||
return flow_graph_builder_->CheckAssignable(dst_type, dst_name);
|
|
||||||
}
|
|
||||||
return Fragment();
|
|
||||||
}
|
|
||||||
|
|
||||||
Fragment StreamingFlowGraphBuilder::CheckArgumentType(
|
Fragment StreamingFlowGraphBuilder::CheckArgumentType(
|
||||||
LocalVariable* variable,
|
LocalVariable* variable,
|
||||||
const AbstractType& type) {
|
const AbstractType& type) {
|
||||||
|
@ -2773,23 +2752,6 @@ Fragment StreamingFlowGraphBuilder::CheckTypeArgumentBound(
|
||||||
bound, dst_name);
|
bound, dst_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fragment StreamingFlowGraphBuilder::CheckVariableTypeInCheckedMode(
|
|
||||||
intptr_t variable_kernel_position) {
|
|
||||||
if (I->type_checks()) {
|
|
||||||
LocalVariable* variable = LookupVariable(variable_kernel_position);
|
|
||||||
return flow_graph_builder_->CheckVariableTypeInCheckedMode(
|
|
||||||
variable->type(), variable->name());
|
|
||||||
}
|
|
||||||
return Fragment();
|
|
||||||
}
|
|
||||||
|
|
||||||
Fragment StreamingFlowGraphBuilder::CheckVariableTypeInCheckedMode(
|
|
||||||
const AbstractType& dst_type,
|
|
||||||
const String& name_symbol) {
|
|
||||||
return flow_graph_builder_->CheckVariableTypeInCheckedMode(dst_type,
|
|
||||||
name_symbol);
|
|
||||||
}
|
|
||||||
|
|
||||||
Fragment StreamingFlowGraphBuilder::EnterScope(
|
Fragment StreamingFlowGraphBuilder::EnterScope(
|
||||||
intptr_t kernel_offset,
|
intptr_t kernel_offset,
|
||||||
const LocalScope** scope /* = nullptr */) {
|
const LocalScope** scope /* = nullptr */) {
|
||||||
|
@ -2973,7 +2935,6 @@ Fragment StreamingFlowGraphBuilder::BuildVariableSet(TokenPosition* p) {
|
||||||
if (NeedsDebugStepCheck(stack(), position)) {
|
if (NeedsDebugStepCheck(stack(), position)) {
|
||||||
instructions = DebugStepCheck(position) + instructions;
|
instructions = DebugStepCheck(position) + instructions;
|
||||||
}
|
}
|
||||||
instructions += CheckVariableTypeInCheckedMode(variable_kernel_position);
|
|
||||||
instructions +=
|
instructions +=
|
||||||
StoreLocal(position, LookupVariable(variable_kernel_position));
|
StoreLocal(position, LookupVariable(variable_kernel_position));
|
||||||
return instructions;
|
return instructions;
|
||||||
|
@ -2990,7 +2951,6 @@ Fragment StreamingFlowGraphBuilder::BuildVariableSet(uint8_t payload,
|
||||||
if (NeedsDebugStepCheck(stack(), position)) {
|
if (NeedsDebugStepCheck(stack(), position)) {
|
||||||
instructions = DebugStepCheck(position) + instructions;
|
instructions = DebugStepCheck(position) + instructions;
|
||||||
}
|
}
|
||||||
instructions += CheckVariableTypeInCheckedMode(variable_kernel_position);
|
|
||||||
instructions +=
|
instructions +=
|
||||||
StoreLocal(position, LookupVariable(variable_kernel_position));
|
StoreLocal(position, LookupVariable(variable_kernel_position));
|
||||||
|
|
||||||
|
@ -3023,7 +2983,7 @@ Fragment StreamingFlowGraphBuilder::BuildPropertyGet(TokenPosition* p) {
|
||||||
const Function* interface_target = &Function::null_function();
|
const Function* interface_target = &Function::null_function();
|
||||||
const NameIndex itarget_name =
|
const NameIndex itarget_name =
|
||||||
ReadCanonicalNameReference(); // read interface_target_reference.
|
ReadCanonicalNameReference(); // read interface_target_reference.
|
||||||
if (FLAG_strong && !H.IsRoot(itarget_name) &&
|
if (!H.IsRoot(itarget_name) &&
|
||||||
(H.IsGetter(itarget_name) || H.IsField(itarget_name))) {
|
(H.IsGetter(itarget_name) || H.IsField(itarget_name))) {
|
||||||
interface_target = &Function::ZoneHandle(
|
interface_target = &Function::ZoneHandle(
|
||||||
Z,
|
Z,
|
||||||
|
@ -3103,7 +3063,7 @@ Fragment StreamingFlowGraphBuilder::BuildPropertySet(TokenPosition* p) {
|
||||||
const Function* interface_target = &Function::null_function();
|
const Function* interface_target = &Function::null_function();
|
||||||
const NameIndex itarget_name =
|
const NameIndex itarget_name =
|
||||||
ReadCanonicalNameReference(); // read interface_target_reference.
|
ReadCanonicalNameReference(); // read interface_target_reference.
|
||||||
if (FLAG_strong && !H.IsRoot(itarget_name)) {
|
if (!H.IsRoot(itarget_name)) {
|
||||||
interface_target = &Function::ZoneHandle(
|
interface_target = &Function::ZoneHandle(
|
||||||
Z,
|
Z,
|
||||||
H.LookupMethodByMember(itarget_name, H.DartSetterName(itarget_name)));
|
H.LookupMethodByMember(itarget_name, H.DartSetterName(itarget_name)));
|
||||||
|
@ -3515,13 +3475,10 @@ Fragment StreamingFlowGraphBuilder::BuildStaticSet(TokenPosition* p) {
|
||||||
if (H.IsField(target)) {
|
if (H.IsField(target)) {
|
||||||
const Field& field =
|
const Field& field =
|
||||||
Field::ZoneHandle(Z, H.LookupFieldByKernelField(target));
|
Field::ZoneHandle(Z, H.LookupFieldByKernelField(target));
|
||||||
const AbstractType& dst_type = AbstractType::ZoneHandle(Z, field.type());
|
|
||||||
Fragment instructions = BuildExpression(); // read expression.
|
Fragment instructions = BuildExpression(); // read expression.
|
||||||
if (NeedsDebugStepCheck(stack(), position)) {
|
if (NeedsDebugStepCheck(stack(), position)) {
|
||||||
instructions = DebugStepCheck(position) + instructions;
|
instructions = DebugStepCheck(position) + instructions;
|
||||||
}
|
}
|
||||||
instructions += CheckAssignableInCheckedMode(
|
|
||||||
dst_type, String::ZoneHandle(Z, field.name()));
|
|
||||||
LocalVariable* variable = MakeTemporary();
|
LocalVariable* variable = MakeTemporary();
|
||||||
instructions += LoadLocal(variable);
|
instructions += LoadLocal(variable);
|
||||||
return instructions + StoreStaticField(position, field);
|
return instructions + StoreStaticField(position, field);
|
||||||
|
@ -3619,7 +3576,7 @@ Fragment StreamingFlowGraphBuilder::BuildMethodInvocation(TokenPosition* p) {
|
||||||
|
|
||||||
intptr_t type_args_len = 0;
|
intptr_t type_args_len = 0;
|
||||||
LocalVariable* type_arguments_temp = NULL;
|
LocalVariable* type_arguments_temp = NULL;
|
||||||
if (FLAG_reify_generic_functions) {
|
{
|
||||||
AlternativeReadingScope alt(&reader_);
|
AlternativeReadingScope alt(&reader_);
|
||||||
SkipExpression(); // skip receiver
|
SkipExpression(); // skip receiver
|
||||||
SkipName(); // skip method name
|
SkipName(); // skip method name
|
||||||
|
@ -3707,7 +3664,7 @@ Fragment StreamingFlowGraphBuilder::BuildMethodInvocation(TokenPosition* p) {
|
||||||
const Function* interface_target = &Function::null_function();
|
const Function* interface_target = &Function::null_function();
|
||||||
const NameIndex itarget_name =
|
const NameIndex itarget_name =
|
||||||
ReadCanonicalNameReference(); // read interface_target_reference.
|
ReadCanonicalNameReference(); // read interface_target_reference.
|
||||||
if (FLAG_strong && !H.IsRoot(itarget_name) && !H.IsField(itarget_name)) {
|
if (!H.IsRoot(itarget_name) && !H.IsField(itarget_name)) {
|
||||||
interface_target = &Function::ZoneHandle(
|
interface_target = &Function::ZoneHandle(
|
||||||
Z, H.LookupMethodByMember(itarget_name,
|
Z, H.LookupMethodByMember(itarget_name,
|
||||||
H.DartProcedureName(itarget_name)));
|
H.DartProcedureName(itarget_name)));
|
||||||
|
@ -3807,7 +3764,7 @@ Fragment StreamingFlowGraphBuilder::BuildDirectMethodInvocation(
|
||||||
|
|
||||||
Fragment instructions;
|
Fragment instructions;
|
||||||
intptr_t type_args_len = 0;
|
intptr_t type_args_len = 0;
|
||||||
if (FLAG_reify_generic_functions) {
|
{
|
||||||
AlternativeReadingScope alt(&reader_);
|
AlternativeReadingScope alt(&reader_);
|
||||||
SkipExpression(); // skip receiver
|
SkipExpression(); // skip receiver
|
||||||
ReadCanonicalNameReference(); // skip target reference
|
ReadCanonicalNameReference(); // skip target reference
|
||||||
|
@ -3873,7 +3830,7 @@ Fragment StreamingFlowGraphBuilder::BuildSuperMethodInvocation(
|
||||||
inferred_type_metadata_helper_.GetInferredType(offset);
|
inferred_type_metadata_helper_.GetInferredType(offset);
|
||||||
|
|
||||||
intptr_t type_args_len = 0;
|
intptr_t type_args_len = 0;
|
||||||
if (FLAG_reify_generic_functions) {
|
{
|
||||||
AlternativeReadingScope alt(&reader_);
|
AlternativeReadingScope alt(&reader_);
|
||||||
SkipName(); // skip method name
|
SkipName(); // skip method name
|
||||||
ReadUInt(); // read argument count.
|
ReadUInt(); // read argument count.
|
||||||
|
@ -3977,7 +3934,7 @@ Fragment StreamingFlowGraphBuilder::BuildSuperMethodInvocation(
|
||||||
} else {
|
} else {
|
||||||
Fragment instructions;
|
Fragment instructions;
|
||||||
|
|
||||||
if (FLAG_reify_generic_functions) {
|
{
|
||||||
AlternativeReadingScope alt(&reader_);
|
AlternativeReadingScope alt(&reader_);
|
||||||
ReadUInt(); // read argument count.
|
ReadUInt(); // read argument count.
|
||||||
intptr_t list_length = ReadListLength(); // read types list length.
|
intptr_t list_length = ReadListLength(); // read types list length.
|
||||||
|
@ -4086,7 +4043,7 @@ Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(bool is_const,
|
||||||
const TypeArguments& type_arguments = PeekArgumentsInstantiatedType(klass);
|
const TypeArguments& type_arguments = PeekArgumentsInstantiatedType(klass);
|
||||||
instructions += TranslateInstantiatedTypeArguments(type_arguments);
|
instructions += TranslateInstantiatedTypeArguments(type_arguments);
|
||||||
instructions += PushArgument();
|
instructions += PushArgument();
|
||||||
} else if (!special_case && FLAG_reify_generic_functions) {
|
} else if (!special_case) {
|
||||||
AlternativeReadingScope alt(&reader_);
|
AlternativeReadingScope alt(&reader_);
|
||||||
ReadUInt(); // read argument count.
|
ReadUInt(); // read argument count.
|
||||||
intptr_t list_length = ReadListLength(); // read types list length.
|
intptr_t list_length = ReadListLength(); // read types list length.
|
||||||
|
@ -4150,31 +4107,6 @@ Fragment StreamingFlowGraphBuilder::BuildConstructorInvocation(
|
||||||
|
|
||||||
Fragment instructions;
|
Fragment instructions;
|
||||||
|
|
||||||
// Check for malbounded-ness of type.
|
|
||||||
if (I->type_checks()) {
|
|
||||||
intptr_t offset = ReaderOffset();
|
|
||||||
|
|
||||||
const TypeArguments& type_arguments = BuildTypeArguments();
|
|
||||||
|
|
||||||
AbstractType& type = AbstractType::Handle(
|
|
||||||
Z, Type::New(klass, type_arguments, TokenPosition::kNoSource));
|
|
||||||
type = ClassFinalizer::FinalizeType(klass, type);
|
|
||||||
|
|
||||||
if (type.IsMalbounded()) {
|
|
||||||
// Evaluate expressions for correctness.
|
|
||||||
instructions +=
|
|
||||||
BuildArgumentsFromActualArguments(NULL, false, /*do_drop*/ true);
|
|
||||||
|
|
||||||
// Throw an error & keep the [Value] on the stack.
|
|
||||||
instructions += ThrowTypeError();
|
|
||||||
|
|
||||||
// Bail out early.
|
|
||||||
return instructions;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetOffset(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (klass.NumTypeArguments() > 0) {
|
if (klass.NumTypeArguments() > 0) {
|
||||||
if (!klass.IsGeneric()) {
|
if (!klass.IsGeneric()) {
|
||||||
Type& type = Type::ZoneHandle(Z, T.ReceiverType(klass).raw());
|
Type& type = Type::ZoneHandle(Z, T.ReceiverType(klass).raw());
|
||||||
|
@ -4291,10 +4223,6 @@ Fragment StreamingFlowGraphBuilder::TranslateLogicalExpressionForValue(
|
||||||
const bool is_bool = top->IsStrictCompare() || top->IsBooleanNegate();
|
const bool is_bool = top->IsStrictCompare() || top->IsBooleanNegate();
|
||||||
if (!is_bool) {
|
if (!is_bool) {
|
||||||
right_value += CheckBoolean(position);
|
right_value += CheckBoolean(position);
|
||||||
if (!FLAG_strong) {
|
|
||||||
right_value += Constant(Bool::True());
|
|
||||||
right_value += StrictCompare(Token::kEQ_STRICT);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (negated) {
|
if (negated) {
|
||||||
right_value += BooleanNegate();
|
right_value += BooleanNegate();
|
||||||
|
@ -4607,23 +4535,12 @@ Fragment StreamingFlowGraphBuilder::BuildListLiteral(bool is_const,
|
||||||
instructions += LoadLocal(type);
|
instructions += LoadLocal(type);
|
||||||
instructions += IntConstant(length);
|
instructions += IntConstant(length);
|
||||||
instructions += CreateArray();
|
instructions += CreateArray();
|
||||||
AbstractType& list_type = AbstractType::ZoneHandle(Z);
|
|
||||||
if (I->type_checks()) {
|
|
||||||
if (type_arguments.IsNull()) {
|
|
||||||
// It was dynamic.
|
|
||||||
list_type = Object::dynamic_type().raw();
|
|
||||||
} else {
|
|
||||||
list_type = type_arguments.TypeAt(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LocalVariable* array = MakeTemporary();
|
LocalVariable* array = MakeTemporary();
|
||||||
for (intptr_t i = 0; i < length; ++i) {
|
for (intptr_t i = 0; i < length; ++i) {
|
||||||
instructions += LoadLocal(array);
|
instructions += LoadLocal(array);
|
||||||
instructions += IntConstant(i);
|
instructions += IntConstant(i);
|
||||||
instructions += BuildExpression(); // read ith expression.
|
instructions += BuildExpression(); // read ith expression.
|
||||||
instructions += CheckAssignableInCheckedMode(
|
|
||||||
list_type, Symbols::ListLiteralElement());
|
|
||||||
instructions += StoreIndexed(kArrayCid);
|
instructions += StoreIndexed(kArrayCid);
|
||||||
instructions += Drop();
|
instructions += Drop();
|
||||||
}
|
}
|
||||||
|
@ -5840,9 +5757,8 @@ Fragment StreamingFlowGraphBuilder::BuildVariableDeclaration() {
|
||||||
|
|
||||||
VariableDeclarationHelper helper(this);
|
VariableDeclarationHelper helper(this);
|
||||||
helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
|
helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
|
||||||
String& name = H.DartSymbolObfuscate(helper.name_index_);
|
T.BuildType(); // read type.
|
||||||
AbstractType& type = T.BuildType(); // read type.
|
Tag tag = ReadTag(); // read (first part of) initializer.
|
||||||
Tag tag = ReadTag(); // read (first part of) initializer.
|
|
||||||
|
|
||||||
Fragment instructions;
|
Fragment instructions;
|
||||||
if (tag == kNothing) {
|
if (tag == kNothing) {
|
||||||
|
@ -5858,7 +5774,6 @@ Fragment StreamingFlowGraphBuilder::BuildVariableDeclaration() {
|
||||||
} else {
|
} else {
|
||||||
// Initializer
|
// Initializer
|
||||||
instructions += BuildExpression(); // read (actual) initializer.
|
instructions += BuildExpression(); // read (actual) initializer.
|
||||||
instructions += CheckVariableTypeInCheckedMode(type, name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -318,15 +318,10 @@ class StreamingFlowGraphBuilder : public KernelReaderHelper {
|
||||||
Fragment Goto(JoinEntryInstr* destination);
|
Fragment Goto(JoinEntryInstr* destination);
|
||||||
Fragment BuildImplicitClosureCreation(const Function& target);
|
Fragment BuildImplicitClosureCreation(const Function& target);
|
||||||
Fragment CheckBoolean(TokenPosition position);
|
Fragment CheckBoolean(TokenPosition position);
|
||||||
Fragment CheckAssignableInCheckedMode(const AbstractType& dst_type,
|
|
||||||
const String& dst_name);
|
|
||||||
Fragment CheckArgumentType(LocalVariable* variable, const AbstractType& type);
|
Fragment CheckArgumentType(LocalVariable* variable, const AbstractType& type);
|
||||||
Fragment CheckTypeArgumentBound(const AbstractType& parameter,
|
Fragment CheckTypeArgumentBound(const AbstractType& parameter,
|
||||||
const AbstractType& bound,
|
const AbstractType& bound,
|
||||||
const String& dst_name);
|
const String& dst_name);
|
||||||
Fragment CheckVariableTypeInCheckedMode(intptr_t variable_kernel_position);
|
|
||||||
Fragment CheckVariableTypeInCheckedMode(const AbstractType& dst_type,
|
|
||||||
const String& name_symbol);
|
|
||||||
Fragment EnterScope(intptr_t kernel_offset,
|
Fragment EnterScope(intptr_t kernel_offset,
|
||||||
const LocalScope** scope = nullptr);
|
const LocalScope** scope = nullptr);
|
||||||
Fragment ExitScope(intptr_t kernel_offset);
|
Fragment ExitScope(intptr_t kernel_offset);
|
||||||
|
|
|
@ -297,14 +297,14 @@ void KernelFingerprintHelper::CalculateFunctionTypeFingerprint(bool simple) {
|
||||||
|
|
||||||
void KernelFingerprintHelper::CalculateGetterNameFingerprint() {
|
void KernelFingerprintHelper::CalculateGetterNameFingerprint() {
|
||||||
const NameIndex name = ReadCanonicalNameReference();
|
const NameIndex name = ReadCanonicalNameReference();
|
||||||
if (FLAG_strong && !H.IsRoot(name) && (H.IsGetter(name) || H.IsField(name))) {
|
if (!H.IsRoot(name) && (H.IsGetter(name) || H.IsField(name))) {
|
||||||
BuildHash(H.DartGetterName(name).Hash());
|
BuildHash(H.DartGetterName(name).Hash());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KernelFingerprintHelper::CalculateSetterNameFingerprint() {
|
void KernelFingerprintHelper::CalculateSetterNameFingerprint() {
|
||||||
const NameIndex name = ReadCanonicalNameReference();
|
const NameIndex name = ReadCanonicalNameReference();
|
||||||
if (FLAG_strong && !H.IsRoot(name)) {
|
if (!H.IsRoot(name)) {
|
||||||
BuildHash(H.DartSetterName(name).Hash());
|
BuildHash(H.DartSetterName(name).Hash());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -312,7 +312,7 @@ void KernelFingerprintHelper::CalculateSetterNameFingerprint() {
|
||||||
void KernelFingerprintHelper::CalculateMethodNameFingerprint() {
|
void KernelFingerprintHelper::CalculateMethodNameFingerprint() {
|
||||||
const NameIndex name =
|
const NameIndex name =
|
||||||
ReadCanonicalNameReference(); // read interface_target_reference.
|
ReadCanonicalNameReference(); // read interface_target_reference.
|
||||||
if (FLAG_strong && !H.IsRoot(name) && !H.IsField(name)) {
|
if (!H.IsRoot(name) && !H.IsField(name)) {
|
||||||
BuildHash(H.DartProcedureName(name).Hash());
|
BuildHash(H.DartProcedureName(name).Hash());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,10 +154,6 @@ Fragment FlowGraphBuilder::LoadInstantiatorTypeArguments() {
|
||||||
// arguments of the current function.
|
// arguments of the current function.
|
||||||
Fragment FlowGraphBuilder::LoadFunctionTypeArguments() {
|
Fragment FlowGraphBuilder::LoadFunctionTypeArguments() {
|
||||||
Fragment instructions;
|
Fragment instructions;
|
||||||
if (!FLAG_reify_generic_functions) {
|
|
||||||
instructions += NullConstant();
|
|
||||||
return instructions;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Function& function = parsed_function_->function();
|
const Function& function = parsed_function_->function();
|
||||||
|
|
||||||
|
@ -442,8 +438,7 @@ Fragment FlowGraphBuilder::NativeCall(const String* name,
|
||||||
const Function* function) {
|
const Function* function) {
|
||||||
InlineBailout("kernel::FlowGraphBuilder::NativeCall");
|
InlineBailout("kernel::FlowGraphBuilder::NativeCall");
|
||||||
const intptr_t num_args =
|
const intptr_t num_args =
|
||||||
function->NumParameters() +
|
function->NumParameters() + (function->IsGeneric() ? 1 : 0);
|
||||||
((function->IsGeneric() && FLAG_reify_generic_functions) ? 1 : 0);
|
|
||||||
ArgumentArray arguments = GetArguments(num_args);
|
ArgumentArray arguments = GetArguments(num_args);
|
||||||
NativeCallInstr* call =
|
NativeCallInstr* call =
|
||||||
new (Z) NativeCallInstr(name, function, FLAG_link_natives_lazily,
|
new (Z) NativeCallInstr(name, function, FLAG_link_natives_lazily,
|
||||||
|
@ -459,8 +454,7 @@ Fragment FlowGraphBuilder::Return(TokenPosition position,
|
||||||
|
|
||||||
// Emit a type check of the return type in checked mode for all functions
|
// Emit a type check of the return type in checked mode for all functions
|
||||||
// and in strong mode for native functions.
|
// and in strong mode for native functions.
|
||||||
if (!omit_result_type_check &&
|
if (!omit_result_type_check && function.is_native()) {
|
||||||
(I->type_checks() || (function.is_native() && FLAG_strong))) {
|
|
||||||
const AbstractType& return_type =
|
const AbstractType& return_type =
|
||||||
AbstractType::Handle(Z, function.result_type());
|
AbstractType::Handle(Z, function.result_type());
|
||||||
instructions += CheckAssignable(return_type, Symbols::FunctionResult());
|
instructions += CheckAssignable(return_type, Symbols::FunctionResult());
|
||||||
|
@ -587,23 +581,6 @@ Fragment FlowGraphBuilder::StaticCall(TokenPosition position,
|
||||||
return Fragment(call);
|
return Fragment(call);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fragment FlowGraphBuilder::StoreInstanceFieldGuarded(
|
|
||||||
const Field& field,
|
|
||||||
bool is_initialization_store) {
|
|
||||||
Fragment instructions;
|
|
||||||
|
|
||||||
const AbstractType& dst_type = AbstractType::ZoneHandle(Z, field.type());
|
|
||||||
if (I->type_checks()) {
|
|
||||||
instructions +=
|
|
||||||
CheckAssignable(dst_type, String::ZoneHandle(Z, field.name()));
|
|
||||||
}
|
|
||||||
|
|
||||||
instructions += BaseFlowGraphBuilder::StoreInstanceFieldGuarded(
|
|
||||||
field, is_initialization_store);
|
|
||||||
|
|
||||||
return instructions;
|
|
||||||
}
|
|
||||||
|
|
||||||
Fragment FlowGraphBuilder::StringInterpolate(TokenPosition position) {
|
Fragment FlowGraphBuilder::StringInterpolate(TokenPosition position) {
|
||||||
Value* array = Pop();
|
Value* array = Pop();
|
||||||
StringInterpolateInstr* interpolate =
|
StringInterpolateInstr* interpolate =
|
||||||
|
@ -921,7 +898,7 @@ Fragment FlowGraphBuilder::NativeFunctionBody(const Function& function,
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
String& name = String::ZoneHandle(Z, function.native_name());
|
String& name = String::ZoneHandle(Z, function.native_name());
|
||||||
if (function.IsGeneric() && FLAG_reify_generic_functions) {
|
if (function.IsGeneric()) {
|
||||||
body += LoadLocal(parsed_function_->RawTypeArgumentsVariable());
|
body += LoadLocal(parsed_function_->RawTypeArgumentsVariable());
|
||||||
body += PushArgument();
|
body += PushArgument();
|
||||||
}
|
}
|
||||||
|
@ -1032,9 +1009,6 @@ Fragment FlowGraphBuilder::BuildImplicitClosureCreation(
|
||||||
Fragment FlowGraphBuilder::CheckVariableTypeInCheckedMode(
|
Fragment FlowGraphBuilder::CheckVariableTypeInCheckedMode(
|
||||||
const AbstractType& dst_type,
|
const AbstractType& dst_type,
|
||||||
const String& name_symbol) {
|
const String& name_symbol) {
|
||||||
if (I->type_checks()) {
|
|
||||||
return CheckAssignable(dst_type, name_symbol);
|
|
||||||
}
|
|
||||||
return Fragment();
|
return Fragment();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1078,12 +1052,10 @@ Fragment FlowGraphBuilder::EvaluateAssertion() {
|
||||||
|
|
||||||
Fragment FlowGraphBuilder::CheckBoolean(TokenPosition position) {
|
Fragment FlowGraphBuilder::CheckBoolean(TokenPosition position) {
|
||||||
Fragment instructions;
|
Fragment instructions;
|
||||||
if (FLAG_strong || I->type_checks() || I->asserts()) {
|
LocalVariable* top_of_stack = MakeTemporary();
|
||||||
LocalVariable* top_of_stack = MakeTemporary();
|
instructions += LoadLocal(top_of_stack);
|
||||||
instructions += LoadLocal(top_of_stack);
|
instructions += AssertBool(position);
|
||||||
instructions += AssertBool(position);
|
instructions += Drop();
|
||||||
instructions += Drop();
|
|
||||||
}
|
|
||||||
return instructions;
|
return instructions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -137,8 +137,6 @@ class FlowGraphBuilder : public BaseFlowGraphBuilder {
|
||||||
const InferredTypeMetadata* result_type = NULL,
|
const InferredTypeMetadata* result_type = NULL,
|
||||||
intptr_t type_args_len = 0,
|
intptr_t type_args_len = 0,
|
||||||
bool use_unchecked_entry = false);
|
bool use_unchecked_entry = false);
|
||||||
Fragment StoreInstanceFieldGuarded(const Field& field,
|
|
||||||
bool is_initialization_store);
|
|
||||||
Fragment StringInterpolate(TokenPosition position);
|
Fragment StringInterpolate(TokenPosition position);
|
||||||
Fragment StringInterpolateSingle(TokenPosition position);
|
Fragment StringInterpolateSingle(TokenPosition position);
|
||||||
Fragment ThrowTypeError();
|
Fragment ThrowTypeError();
|
||||||
|
|
|
@ -2944,16 +2944,12 @@ void TypeTranslator::BuildTypeParameterType() {
|
||||||
: 0;
|
: 0;
|
||||||
if (procedure_type_parameter_count > 0) {
|
if (procedure_type_parameter_count > 0) {
|
||||||
if (procedure_type_parameter_count > parameter_index) {
|
if (procedure_type_parameter_count > parameter_index) {
|
||||||
if (FLAG_reify_generic_functions) {
|
result_ ^=
|
||||||
result_ ^=
|
TypeArguments::Handle(Z, active_class_->member->type_parameters())
|
||||||
TypeArguments::Handle(Z, active_class_->member->type_parameters())
|
.TypeAt(parameter_index);
|
||||||
.TypeAt(parameter_index);
|
if (finalize_) {
|
||||||
if (finalize_) {
|
result_ =
|
||||||
result_ =
|
ClassFinalizer::FinalizeType(*active_class_->klass, result_);
|
||||||
ClassFinalizer::FinalizeType(*active_class_->klass, result_);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
result_ ^= Type::DynamicType();
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2963,12 +2959,7 @@ void TypeTranslator::BuildTypeParameterType() {
|
||||||
|
|
||||||
if (active_class_->local_type_parameters != NULL) {
|
if (active_class_->local_type_parameters != NULL) {
|
||||||
if (parameter_index < active_class_->local_type_parameters->Length()) {
|
if (parameter_index < active_class_->local_type_parameters->Length()) {
|
||||||
if (FLAG_reify_generic_functions) {
|
result_ ^= active_class_->local_type_parameters->TypeAt(parameter_index);
|
||||||
result_ ^=
|
|
||||||
active_class_->local_type_parameters->TypeAt(parameter_index);
|
|
||||||
} else {
|
|
||||||
result_ ^= Type::DynamicType();
|
|
||||||
}
|
|
||||||
if (finalize_) {
|
if (finalize_) {
|
||||||
result_ = ClassFinalizer::FinalizeType(*active_class_->klass, result_);
|
result_ = ClassFinalizer::FinalizeType(*active_class_->klass, result_);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,8 +40,7 @@ BlockEntryInstr* PrologueBuilder::BuildPrologue(BlockEntryInstr* entry,
|
||||||
const intptr_t previous_block_id = last_used_block_id_;
|
const intptr_t previous_block_id = last_used_block_id_;
|
||||||
|
|
||||||
const bool load_optional_arguments = function_.HasOptionalParameters();
|
const bool load_optional_arguments = function_.HasOptionalParameters();
|
||||||
const bool expect_type_args =
|
const bool expect_type_args = function_.IsGeneric();
|
||||||
function_.IsGeneric() && FLAG_reify_generic_functions;
|
|
||||||
const bool check_arguments = function_.IsClosureFunction();
|
const bool check_arguments = function_.IsClosureFunction();
|
||||||
|
|
||||||
Fragment prologue = Fragment(entry);
|
Fragment prologue = Fragment(entry);
|
||||||
|
|
|
@ -113,8 +113,7 @@ ScopeBuildingResult* ScopeBuilder::BuildScopes() {
|
||||||
scope_->set_end_token_pos(function.end_token_pos());
|
scope_->set_end_token_pos(function.end_token_pos());
|
||||||
|
|
||||||
// Add function type arguments variable before current context variable.
|
// Add function type arguments variable before current context variable.
|
||||||
if (FLAG_reify_generic_functions &&
|
if ((function.IsGeneric() || function.HasGenericParent())) {
|
||||||
(function.IsGeneric() || function.HasGenericParent())) {
|
|
||||||
LocalVariable* type_args_var = MakeVariable(
|
LocalVariable* type_args_var = MakeVariable(
|
||||||
TokenPosition::kNoSource, TokenPosition::kNoSource,
|
TokenPosition::kNoSource, TokenPosition::kNoSource,
|
||||||
Symbols::FunctionTypeArgumentsVar(), AbstractType::dynamic_type());
|
Symbols::FunctionTypeArgumentsVar(), AbstractType::dynamic_type());
|
||||||
|
|
|
@ -94,7 +94,7 @@ intptr_t MethodRecognizer::ResultCid(const Function& function) {
|
||||||
#define DEFINE_CASE(cname, fname, ename, result_type, fingerprint) \
|
#define DEFINE_CASE(cname, fname, ename, result_type, fingerprint) \
|
||||||
case k##ename: { \
|
case k##ename: { \
|
||||||
const intptr_t cid = k##result_type##Cid; \
|
const intptr_t cid = k##result_type##Cid; \
|
||||||
if (FLAG_strong && cid != kDynamicCid) { \
|
if (cid != kDynamicCid) { \
|
||||||
String& err = String::Handle(); \
|
String& err = String::Handle(); \
|
||||||
err = function.QualifiedScrubbedName(); \
|
err = function.QualifiedScrubbedName(); \
|
||||||
err = String::Concat( \
|
err = String::Concat( \
|
||||||
|
|
|
@ -326,7 +326,7 @@ char* Dart::Init(const uint8_t* vm_isolate_snapshot,
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool is_dart2_aot_precompiler =
|
const bool is_dart2_aot_precompiler =
|
||||||
FLAG_strong && FLAG_precompiled_mode && !kDartPrecompiledRuntime;
|
FLAG_precompiled_mode && !kDartPrecompiledRuntime;
|
||||||
|
|
||||||
if (!is_dart2_aot_precompiler &&
|
if (!is_dart2_aot_precompiler &&
|
||||||
(FLAG_support_service || !kDartPrecompiledRuntime)) {
|
(FLAG_support_service || !kDartPrecompiledRuntime)) {
|
||||||
|
@ -717,25 +717,11 @@ const char* Dart::FeaturesString(Isolate* isolate,
|
||||||
buffer.AddString(name ? (" " #name) : (" no-" #name)); \
|
buffer.AddString(name ? (" " #name) : (" no-" #name)); \
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
// We don't write the strong flag into the features list for the VM isolate
|
|
||||||
// snapshot as the implementation is in an intermediate state where the VM
|
|
||||||
// isolate is always initialized from a vm_snapshot generated in non strong
|
|
||||||
// mode.
|
|
||||||
if (!is_vm_isolate) {
|
|
||||||
buffer.AddString(FLAG_strong ? " strong" : " no-strong");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Snapshot::IncludesCode(kind)) {
|
if (Snapshot::IncludesCode(kind)) {
|
||||||
// Checked mode affects deopt ids.
|
// enabling assertions affects deopt ids.
|
||||||
ADD_FLAG(type_checks, enable_type_checks, FLAG_enable_type_checks);
|
|
||||||
ADD_FLAG(asserts, enable_asserts, FLAG_enable_asserts);
|
ADD_FLAG(asserts, enable_asserts, FLAG_enable_asserts);
|
||||||
ADD_FLAG(error_on_bad_type, enable_error_on_bad_type,
|
// sync-async affects deopt_ids.
|
||||||
FLAG_error_on_bad_type);
|
|
||||||
// sync-async and reify_generic_functions also affect deopt_ids.
|
|
||||||
buffer.AddString(FLAG_sync_async ? " sync_async" : " no-sync_async");
|
buffer.AddString(FLAG_sync_async ? " sync_async" : " no-sync_async");
|
||||||
buffer.AddString(FLAG_reify_generic_functions
|
|
||||||
? " reify_generic_functions"
|
|
||||||
: " no-reify_generic_functions");
|
|
||||||
if (kind == Snapshot::kFullJIT) {
|
if (kind == Snapshot::kFullJIT) {
|
||||||
ADD_FLAG(use_field_guards, use_field_guards, FLAG_use_field_guards);
|
ADD_FLAG(use_field_guards, use_field_guards, FLAG_use_field_guards);
|
||||||
ADD_FLAG(use_osr, use_osr, FLAG_use_osr);
|
ADD_FLAG(use_osr, use_osr, FLAG_use_osr);
|
||||||
|
|
|
@ -3591,9 +3591,7 @@ VM_UNIT_TEST_CASE(DartAPI_IsolateSetCheckedMode) {
|
||||||
// Create an isolate with checked mode flags.
|
// Create an isolate with checked mode flags.
|
||||||
Dart_IsolateFlags api_flags;
|
Dart_IsolateFlags api_flags;
|
||||||
Isolate::FlagsInitialize(&api_flags);
|
Isolate::FlagsInitialize(&api_flags);
|
||||||
api_flags.enable_type_checks = true;
|
|
||||||
api_flags.enable_asserts = true;
|
api_flags.enable_asserts = true;
|
||||||
api_flags.enable_error_on_bad_type = true;
|
|
||||||
char* err;
|
char* err;
|
||||||
Dart_Isolate isolate =
|
Dart_Isolate isolate =
|
||||||
Dart_CreateIsolate(NULL, NULL, bin::core_isolate_snapshot_data,
|
Dart_CreateIsolate(NULL, NULL, bin::core_isolate_snapshot_data,
|
||||||
|
|
|
@ -117,7 +117,7 @@ RawObject* DartEntry::InvokeFunction(const Function& function,
|
||||||
// and never start the VM service isolate. So we should never end up invoking
|
// and never start the VM service isolate. So we should never end up invoking
|
||||||
// any dart code in the Dart 2.0 AOT compiler.
|
// any dart code in the Dart 2.0 AOT compiler.
|
||||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||||
if (FLAG_strong && FLAG_precompiled_mode) {
|
if (FLAG_precompiled_mode) {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||||
|
|
|
@ -92,11 +92,6 @@ constexpr bool kDartPrecompiledRuntime = false;
|
||||||
"Compile expressions with the Kernel front-end.") \
|
"Compile expressions with the Kernel front-end.") \
|
||||||
P(enable_mirrors, bool, true, \
|
P(enable_mirrors, bool, true, \
|
||||||
"Disable to make importing dart:mirrors an error.") \
|
"Disable to make importing dart:mirrors an error.") \
|
||||||
R(enable_type_checks, false, bool, false, "Enable type checks.") \
|
|
||||||
R(error_on_bad_override, false, bool, false, \
|
|
||||||
"Report error for bad overrides. Ignored in strong mode.") \
|
|
||||||
R(error_on_bad_type, false, bool, false, \
|
|
||||||
"Report error for malformed types.") \
|
|
||||||
P(fields_may_be_reset, bool, false, \
|
P(fields_may_be_reset, bool, false, \
|
||||||
"Don't optimize away static field initialization") \
|
"Don't optimize away static field initialization") \
|
||||||
C(force_clone_compiler_objects, false, false, bool, false, \
|
C(force_clone_compiler_objects, false, false, bool, false, \
|
||||||
|
@ -158,12 +153,9 @@ constexpr bool kDartPrecompiledRuntime = false;
|
||||||
R(profiler, false, bool, false, "Enable the profiler.") \
|
R(profiler, false, bool, false, "Enable the profiler.") \
|
||||||
R(profiler_native_memory, false, bool, false, \
|
R(profiler_native_memory, false, bool, false, \
|
||||||
"Enable native memory statistic collection.") \
|
"Enable native memory statistic collection.") \
|
||||||
P(reify_generic_functions, bool, true, \
|
|
||||||
"Enable reification of generic functions (not yet supported).") \
|
|
||||||
P(reorder_basic_blocks, bool, true, "Reorder basic blocks") \
|
P(reorder_basic_blocks, bool, true, "Reorder basic blocks") \
|
||||||
C(stress_async_stacks, false, false, bool, false, \
|
C(stress_async_stacks, false, false, bool, false, \
|
||||||
"Stress test async stack traces") \
|
"Stress test async stack traces") \
|
||||||
P(strong, bool, true, "Enable strong mode.") \
|
|
||||||
P(sync_async, bool, true, "Start `async` functions synchronously.") \
|
P(sync_async, bool, true, "Start `async` functions synchronously.") \
|
||||||
R(support_disassembler, false, bool, true, "Support the disassembler.") \
|
R(support_disassembler, false, bool, true, "Support the disassembler.") \
|
||||||
R(support_il_printer, false, bool, true, "Support the IL printer.") \
|
R(support_il_printer, false, bool, true, "Support the IL printer.") \
|
||||||
|
|
|
@ -194,8 +194,7 @@ class InterpreterHelpers {
|
||||||
static bool ObjectArraySetIndexed(Thread* thread,
|
static bool ObjectArraySetIndexed(Thread* thread,
|
||||||
RawObject** FP,
|
RawObject** FP,
|
||||||
RawObject** result) {
|
RawObject** result) {
|
||||||
return !thread->isolate()->type_checks() &&
|
return ObjectArraySetIndexedUnchecked(thread, FP, result);
|
||||||
ObjectArraySetIndexedUnchecked(thread, FP, result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ObjectArraySetIndexedUnchecked(Thread* thread,
|
static bool ObjectArraySetIndexedUnchecked(Thread* thread,
|
||||||
|
@ -228,8 +227,7 @@ class InterpreterHelpers {
|
||||||
static bool GrowableArraySetIndexed(Thread* thread,
|
static bool GrowableArraySetIndexed(Thread* thread,
|
||||||
RawObject** FP,
|
RawObject** FP,
|
||||||
RawObject** result) {
|
RawObject** result) {
|
||||||
return !thread->isolate()->type_checks() &&
|
return GrowableArraySetIndexedUnchecked(thread, FP, result);
|
||||||
GrowableArraySetIndexedUnchecked(thread, FP, result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool GrowableArraySetIndexedUnchecked(Thread* thread,
|
static bool GrowableArraySetIndexedUnchecked(Thread* thread,
|
||||||
|
|
|
@ -68,7 +68,6 @@ DECLARE_FLAG(bool, trace_reload);
|
||||||
#if !defined(PRODUCT)
|
#if !defined(PRODUCT)
|
||||||
static void CheckedModeHandler(bool value) {
|
static void CheckedModeHandler(bool value) {
|
||||||
FLAG_enable_asserts = value;
|
FLAG_enable_asserts = value;
|
||||||
FLAG_enable_type_checks = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --enable-checked-mode and --checked both enable checked mode which is
|
// --enable-checked-mode and --checked both enable checked mode which is
|
||||||
|
|
|
@ -136,11 +136,7 @@ typedef FixedCache<intptr_t, CatchEntryMovesRefPtr, 16> CatchEntryMovesCache;
|
||||||
// V(when, name, Dart_IsolateFlags-member-name, command-line-flag-name)
|
// V(when, name, Dart_IsolateFlags-member-name, command-line-flag-name)
|
||||||
//
|
//
|
||||||
#define ISOLATE_FLAG_LIST(V) \
|
#define ISOLATE_FLAG_LIST(V) \
|
||||||
V(NONPRODUCT, type_checks, EnableTypeChecks, enable_type_checks, \
|
|
||||||
FLAG_enable_type_checks) \
|
|
||||||
V(NONPRODUCT, asserts, EnableAsserts, enable_asserts, FLAG_enable_asserts) \
|
V(NONPRODUCT, asserts, EnableAsserts, enable_asserts, FLAG_enable_asserts) \
|
||||||
V(NONPRODUCT, error_on_bad_type, ErrorOnBadType, enable_error_on_bad_type, \
|
|
||||||
FLAG_error_on_bad_type) \
|
|
||||||
V(NONPRODUCT, use_field_guards, UseFieldGuards, use_field_guards, \
|
V(NONPRODUCT, use_field_guards, UseFieldGuards, use_field_guards, \
|
||||||
FLAG_use_field_guards) \
|
FLAG_use_field_guards) \
|
||||||
V(NONPRODUCT, use_osr, UseOsr, use_osr, FLAG_use_osr) \
|
V(NONPRODUCT, use_osr, UseOsr, use_osr, FLAG_use_osr) \
|
||||||
|
@ -687,8 +683,7 @@ class Isolate : public BaseIsolate {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool can_use_strong_mode_types() const {
|
bool can_use_strong_mode_types() const {
|
||||||
return FLAG_strong && FLAG_use_strong_mode_types &&
|
return FLAG_use_strong_mode_types && !unsafe_trust_strong_mode_types();
|
||||||
!unsafe_trust_strong_mode_types();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool should_load_vmservice() const {
|
bool should_load_vmservice() const {
|
||||||
|
@ -746,12 +741,10 @@ class Isolate : public BaseIsolate {
|
||||||
|
|
||||||
// Convenience flag tester indicating whether incoming function arguments
|
// Convenience flag tester indicating whether incoming function arguments
|
||||||
// should be type checked.
|
// should be type checked.
|
||||||
bool argument_type_checks() const {
|
bool argument_type_checks() const { return should_emit_strong_mode_checks(); }
|
||||||
return should_emit_strong_mode_checks() || type_checks();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool should_emit_strong_mode_checks() const {
|
bool should_emit_strong_mode_checks() const {
|
||||||
return FLAG_strong && !unsafe_trust_strong_mode_types();
|
return !unsafe_trust_strong_mode_types();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void KillAllIsolates(LibMsgId msg_id);
|
static void KillAllIsolates(LibMsgId msg_id);
|
||||||
|
|
|
@ -593,8 +593,6 @@ RawObject* BuildParameterDescriptor(const Function& function) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NeedsDynamicInvocationForwarder(const Function& function) {
|
bool NeedsDynamicInvocationForwarder(const Function& function) {
|
||||||
ASSERT(FLAG_strong);
|
|
||||||
|
|
||||||
Thread* thread = Thread::Current();
|
Thread* thread = Thread::Current();
|
||||||
Zone* zone = thread->zone();
|
Zone* zone = thread->zone();
|
||||||
|
|
||||||
|
|
|
@ -88,9 +88,7 @@ class RunKernelTask : public ThreadPool::Task {
|
||||||
// the app-jit training run (see //utils/kernel-service/BUILD.gn).
|
// the app-jit training run (see //utils/kernel-service/BUILD.gn).
|
||||||
Dart_IsolateFlags api_flags;
|
Dart_IsolateFlags api_flags;
|
||||||
Isolate::FlagsInitialize(&api_flags);
|
Isolate::FlagsInitialize(&api_flags);
|
||||||
api_flags.enable_type_checks = false;
|
|
||||||
api_flags.enable_asserts = false;
|
api_flags.enable_asserts = false;
|
||||||
api_flags.enable_error_on_bad_type = false;
|
|
||||||
api_flags.unsafe_trust_strong_mode_types = false;
|
api_flags.unsafe_trust_strong_mode_types = false;
|
||||||
#if !defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC)
|
#if !defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC)
|
||||||
api_flags.use_field_guards = true;
|
api_flags.use_field_guards = true;
|
||||||
|
@ -547,7 +545,7 @@ class KernelCompilationRequest : public ValueObject {
|
||||||
|
|
||||||
Dart_CObject dart_strong;
|
Dart_CObject dart_strong;
|
||||||
dart_strong.type = Dart_CObject_kBool;
|
dart_strong.type = Dart_CObject_kBool;
|
||||||
dart_strong.value.as_bool = FLAG_strong;
|
dart_strong.value.as_bool = true;
|
||||||
|
|
||||||
// TODO(aam): Assert that isolate exists once we move CompileAndReadScript
|
// TODO(aam): Assert that isolate exists once we move CompileAndReadScript
|
||||||
// compilation logic out of CreateIsolateAndSetupHelper and into
|
// compilation logic out of CreateIsolateAndSetupHelper and into
|
||||||
|
|
|
@ -84,19 +84,7 @@ TEST_CASE(Mixin_PrivateSuperResolutionCrossLibraryShouldFail) {
|
||||||
Dart_Handle lib = TestCase::LoadTestScriptWithDFE(
|
Dart_Handle lib = TestCase::LoadTestScriptWithDFE(
|
||||||
sizeof(sourcefiles) / sizeof(Dart_SourceFile), sourcefiles,
|
sizeof(sourcefiles) / sizeof(Dart_SourceFile), sourcefiles,
|
||||||
/* resolver= */ NULL, /* finalize= */ true, /* incrementally= */ true);
|
/* resolver= */ NULL, /* finalize= */ true, /* incrementally= */ true);
|
||||||
if (FLAG_strong) {
|
EXPECT_ERROR(lib, "Error: Superclass has no method named '_bar'.");
|
||||||
EXPECT_ERROR(lib, "Error: Superclass has no method named '_bar'.");
|
|
||||||
} else {
|
|
||||||
EXPECT_VALID(lib);
|
|
||||||
Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
|
|
||||||
const char* result_str = NULL;
|
|
||||||
EXPECT(Dart_IsString(result));
|
|
||||||
EXPECT_VALID(Dart_StringToCString(result, &result_str));
|
|
||||||
EXPECT_STREQ(
|
|
||||||
"NoSuchMethodError: Super class of class 'D' has no instance method "
|
|
||||||
"'_bar'.",
|
|
||||||
result_str);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
|
#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
|
||||||
|
|
||||||
|
|
|
@ -180,7 +180,7 @@ class NativeArguments {
|
||||||
if (function.IsClosureFunction()) {
|
if (function.IsClosureFunction()) {
|
||||||
function_bits |= kClosureFunctionBit;
|
function_bits |= kClosureFunctionBit;
|
||||||
}
|
}
|
||||||
if (function.IsGeneric() && FLAG_reify_generic_functions) {
|
if (function.IsGeneric()) {
|
||||||
function_bits |= kGenericFunctionBit;
|
function_bits |= kGenericFunctionBit;
|
||||||
argc++;
|
argc++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4310,27 +4310,21 @@ bool Class::TypeTestNonRecursive(const Class& cls,
|
||||||
other.IsVoidClass()) {
|
other.IsVoidClass()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Check for NullType, which, as of Dart 1.5, is a subtype of (and is more
|
// Check for NullType, which, as of Dart 2.0, is a subtype of (and is more
|
||||||
// specific than) any type. Note that the null instance is not handled here.
|
// specific than) any type. Note that the null instance is not handled here.
|
||||||
if (this_class.IsNullClass()) {
|
if (this_class.IsNullClass()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Class FutureOr is mapped to dynamic in non-strong mode.
|
|
||||||
// Detect snapshots compiled in strong mode and run in non-strong mode.
|
|
||||||
ASSERT(FLAG_strong || !other.IsFutureOrClass());
|
|
||||||
// In strong mode, check if 'other' is 'FutureOr'.
|
// In strong mode, check if 'other' is 'FutureOr'.
|
||||||
// If so, apply additional subtyping rules.
|
// If so, apply additional subtyping rules.
|
||||||
if (FLAG_strong && this_class.FutureOrTypeTest(
|
if (this_class.FutureOrTypeTest(zone, type_arguments, other,
|
||||||
zone, type_arguments, other, other_type_arguments,
|
other_type_arguments, bound_error,
|
||||||
bound_error, bound_trail, space)) {
|
bound_trail, space)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// In the case of a subtype test, each occurrence of DynamicType in type S
|
// DynamicType is not more specific than any type.
|
||||||
// is interpreted as the bottom type, a subtype of all types, but not in
|
|
||||||
// strong mode.
|
|
||||||
// However, DynamicType is not more specific than any type.
|
|
||||||
if (this_class.IsDynamicClass()) {
|
if (this_class.IsDynamicClass()) {
|
||||||
return !FLAG_strong && (test_kind == Class::kIsSubtypeOf);
|
return false;
|
||||||
}
|
}
|
||||||
// If other is neither Object, dynamic or void, then ObjectType/VoidType
|
// If other is neither Object, dynamic or void, then ObjectType/VoidType
|
||||||
// can't be a subtype of other.
|
// can't be a subtype of other.
|
||||||
|
@ -4357,21 +4351,12 @@ bool Class::TypeTestNonRecursive(const Class& cls,
|
||||||
// Other type can't be more specific than this one because for that
|
// Other type can't be more specific than this one because for that
|
||||||
// it would have to have all dynamic type arguments which is checked
|
// it would have to have all dynamic type arguments which is checked
|
||||||
// above.
|
// above.
|
||||||
return !FLAG_strong && (test_kind == Class::kIsSubtypeOf);
|
return false;
|
||||||
}
|
}
|
||||||
return type_arguments.TypeTest(test_kind, other_type_arguments,
|
return type_arguments.TypeTest(test_kind, other_type_arguments,
|
||||||
from_index, num_type_params, bound_error,
|
from_index, num_type_params, bound_error,
|
||||||
bound_trail, space);
|
bound_trail, space);
|
||||||
}
|
}
|
||||||
// In strong mode, subtyping rules of callable instances are restricted.
|
|
||||||
if (!FLAG_strong && other.IsDartFunctionClass()) {
|
|
||||||
// Check if type S has a call() method.
|
|
||||||
const Function& call_function =
|
|
||||||
Function::Handle(zone, this_class.LookupCallFunctionForTypeTest());
|
|
||||||
if (!call_function.IsNull()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check for 'direct super type' specified in the implements clause
|
// Check for 'direct super type' specified in the implements clause
|
||||||
// and check for transitivity at the same time.
|
// and check for transitivity at the same time.
|
||||||
Array& interfaces = Array::Handle(zone, this_class.interfaces());
|
Array& interfaces = Array::Handle(zone, this_class.interfaces());
|
||||||
|
@ -4424,7 +4409,7 @@ bool Class::TypeTestNonRecursive(const Class& cls,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// In Dart 2, implementing Function has no meaning.
|
// In Dart 2, implementing Function has no meaning.
|
||||||
if (FLAG_strong && interface_class.IsDartFunctionClass()) {
|
if (interface_class.IsDartFunctionClass()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (interface_class.TypeTest(test_kind, interface_args, other,
|
if (interface_class.TypeTest(test_kind, interface_args, other,
|
||||||
|
@ -4470,7 +4455,6 @@ bool Class::FutureOrTypeTest(Zone* zone,
|
||||||
Heap::Space space) const {
|
Heap::Space space) const {
|
||||||
// In strong mode, there is no difference between 'is subtype of' and
|
// In strong mode, there is no difference between 'is subtype of' and
|
||||||
// 'is more specific than'.
|
// 'is more specific than'.
|
||||||
ASSERT(FLAG_strong);
|
|
||||||
if (other.IsFutureOrClass()) {
|
if (other.IsFutureOrClass()) {
|
||||||
if (other_type_arguments.IsNull()) {
|
if (other_type_arguments.IsNull()) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -4553,31 +4537,6 @@ RawFunction* Class::LookupFunctionAllowPrivate(const String& name) const {
|
||||||
return LookupFunctionAllowPrivate(name, kAny);
|
return LookupFunctionAllowPrivate(name, kAny);
|
||||||
}
|
}
|
||||||
|
|
||||||
RawFunction* Class::LookupCallFunctionForTypeTest() const {
|
|
||||||
// If this class is not compiled yet, it is too early to lookup a call
|
|
||||||
// function. This case should only occur during bounds checking at compile
|
|
||||||
// time. Return null as if the call method did not exist, so the type test
|
|
||||||
// may return false, but without a bound error, and the bound check will get
|
|
||||||
// postponed to runtime.
|
|
||||||
if (!is_finalized()) {
|
|
||||||
return Function::null();
|
|
||||||
}
|
|
||||||
Zone* zone = Thread::Current()->zone();
|
|
||||||
Class& cls = Class::Handle(zone, raw());
|
|
||||||
Function& call_function = Function::Handle(zone);
|
|
||||||
do {
|
|
||||||
ASSERT(cls.is_finalized());
|
|
||||||
call_function = cls.LookupDynamicFunctionAllowAbstract(Symbols::Call());
|
|
||||||
cls = cls.SuperClass();
|
|
||||||
} while (call_function.IsNull() && !cls.IsNull());
|
|
||||||
if (!call_function.IsNull()) {
|
|
||||||
// Make sure the signature is finalized before using it in a type test.
|
|
||||||
ClassFinalizer::FinalizeSignature(
|
|
||||||
cls, call_function, ClassFinalizer::kFinalize); // No bounds checking.
|
|
||||||
}
|
|
||||||
return call_function.raw();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true if 'prefix' and 'accessor_name' match 'name'.
|
// Returns true if 'prefix' and 'accessor_name' match 'name'.
|
||||||
static bool MatchesAccessorName(const String& name,
|
static bool MatchesAccessorName(const String& name,
|
||||||
const char* prefix,
|
const char* prefix,
|
||||||
|
@ -5149,7 +5108,6 @@ RawString* TypeArguments::SubvectorName(intptr_t from_index,
|
||||||
name = type.BuildName(name_visibility);
|
name = type.BuildName(name_visibility);
|
||||||
} else {
|
} else {
|
||||||
// Show dynamic type argument in strong mode.
|
// Show dynamic type argument in strong mode.
|
||||||
ASSERT(FLAG_strong);
|
|
||||||
name = Symbols::Dynamic().raw();
|
name = Symbols::Dynamic().raw();
|
||||||
}
|
}
|
||||||
pieces.Add(name);
|
pieces.Add(name);
|
||||||
|
@ -7248,36 +7206,15 @@ bool Function::TestParameterType(TypeTestKind test_kind,
|
||||||
Error* bound_error,
|
Error* bound_error,
|
||||||
TrailPtr bound_trail,
|
TrailPtr bound_trail,
|
||||||
Heap::Space space) const {
|
Heap::Space space) const {
|
||||||
if (FLAG_strong) {
|
const AbstractType& param_type =
|
||||||
const AbstractType& param_type =
|
AbstractType::Handle(ParameterTypeAt(parameter_position));
|
||||||
AbstractType::Handle(ParameterTypeAt(parameter_position));
|
if (param_type.IsTopType()) {
|
||||||
if (param_type.IsTopType()) {
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
const AbstractType& other_param_type =
|
|
||||||
AbstractType::Handle(other.ParameterTypeAt(other_parameter_position));
|
|
||||||
return other_param_type.IsSubtypeOf(param_type, bound_error, bound_trail,
|
|
||||||
space);
|
|
||||||
}
|
}
|
||||||
const AbstractType& other_param_type =
|
const AbstractType& other_param_type =
|
||||||
AbstractType::Handle(other.ParameterTypeAt(other_parameter_position));
|
AbstractType::Handle(other.ParameterTypeAt(other_parameter_position));
|
||||||
if (other_param_type.IsDynamicType()) {
|
return other_param_type.IsSubtypeOf(param_type, bound_error, bound_trail,
|
||||||
return true;
|
space);
|
||||||
}
|
|
||||||
const AbstractType& param_type =
|
|
||||||
AbstractType::Handle(ParameterTypeAt(parameter_position));
|
|
||||||
if (param_type.IsDynamicType()) {
|
|
||||||
return test_kind == kIsSubtypeOf;
|
|
||||||
}
|
|
||||||
if (test_kind == kIsSubtypeOf) {
|
|
||||||
return param_type.IsSubtypeOf(other_param_type, bound_error, bound_trail,
|
|
||||||
space) ||
|
|
||||||
other_param_type.IsSubtypeOf(param_type, bound_error, bound_trail,
|
|
||||||
space);
|
|
||||||
}
|
|
||||||
ASSERT(test_kind == kIsMoreSpecificThan);
|
|
||||||
return param_type.IsMoreSpecificThan(other_param_type, bound_error,
|
|
||||||
bound_trail, space);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Function::HasSameTypeParametersAndBounds(const Function& other) const {
|
bool Function::HasSameTypeParametersAndBounds(const Function& other) const {
|
||||||
|
@ -7339,48 +7276,21 @@ bool Function::TypeTest(TypeTestKind test_kind,
|
||||||
(num_opt_named_params < other_num_opt_named_params)) {
|
(num_opt_named_params < other_num_opt_named_params)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (FLAG_reify_generic_functions) {
|
// Check the type parameters and bounds of generic functions.
|
||||||
// Check the type parameters and bounds of generic functions.
|
if (!HasSameTypeParametersAndBounds(other)) {
|
||||||
if (!HasSameTypeParametersAndBounds(other)) {
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Thread* thread = Thread::Current();
|
Thread* thread = Thread::Current();
|
||||||
Zone* zone = thread->zone();
|
Zone* zone = thread->zone();
|
||||||
// Check the result type.
|
// Check the result type.
|
||||||
const AbstractType& other_res_type =
|
const AbstractType& other_res_type =
|
||||||
AbstractType::Handle(zone, other.result_type());
|
AbstractType::Handle(zone, other.result_type());
|
||||||
if (FLAG_strong) {
|
// In strong mode, 'void Function()' is a subtype of 'Object Function()'.
|
||||||
// In strong mode, 'void Function()' is a subtype of 'Object Function()'.
|
if (!other_res_type.IsTopType()) {
|
||||||
if (!other_res_type.IsTopType()) {
|
const AbstractType& res_type = AbstractType::Handle(zone, result_type());
|
||||||
const AbstractType& res_type = AbstractType::Handle(zone, result_type());
|
if (!res_type.IsSubtypeOf(other_res_type, bound_error, bound_trail,
|
||||||
if (!res_type.IsSubtypeOf(other_res_type, bound_error, bound_trail,
|
space)) {
|
||||||
space)) {
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// In Dart 1.0, 'void Function()' is not a subtype of 'Object Function()',
|
|
||||||
// but it is a subtype of 'dynamic Function()' and of 'void Function()'.
|
|
||||||
if (!other_res_type.IsDynamicType() && !other_res_type.IsVoidType()) {
|
|
||||||
const AbstractType& res_type = AbstractType::Handle(zone, result_type());
|
|
||||||
if (res_type.IsVoidType()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (test_kind == kIsSubtypeOf) {
|
|
||||||
if (!res_type.IsSubtypeOf(other_res_type, bound_error, bound_trail,
|
|
||||||
space) &&
|
|
||||||
!other_res_type.IsSubtypeOf(res_type, bound_error, bound_trail,
|
|
||||||
space)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ASSERT(test_kind == kIsMoreSpecificThan);
|
|
||||||
if (!res_type.IsMoreSpecificThan(other_res_type, bound_error,
|
|
||||||
bound_trail, space)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check the types of fixed and optional positional parameters.
|
// Check the types of fixed and optional positional parameters.
|
||||||
|
@ -7722,7 +7632,7 @@ RawFunction* Function::ImplicitClosureFunction() const {
|
||||||
// In strong mode, change covariant parameter types to Object in the implicit
|
// In strong mode, change covariant parameter types to Object in the implicit
|
||||||
// closure of a method compiled by kernel.
|
// closure of a method compiled by kernel.
|
||||||
// The VM's parser erases covariant types immediately in strong mode.
|
// The VM's parser erases covariant types immediately in strong mode.
|
||||||
if (FLAG_strong && !is_static() && kernel_offset() > 0) {
|
if (!is_static() && kernel_offset() > 0) {
|
||||||
const Script& function_script = Script::Handle(zone, script());
|
const Script& function_script = Script::Handle(zone, script());
|
||||||
kernel::TranslationHelper translation_helper(thread);
|
kernel::TranslationHelper translation_helper(thread);
|
||||||
translation_helper.InitFromScript(function_script);
|
translation_helper.InitFromScript(function_script);
|
||||||
|
@ -7886,31 +7796,29 @@ RawString* Function::BuildSignature(NameVisibility name_visibility) const {
|
||||||
Zone* zone = thread->zone();
|
Zone* zone = thread->zone();
|
||||||
GrowableHandlePtrArray<const String> pieces(zone, 4);
|
GrowableHandlePtrArray<const String> pieces(zone, 4);
|
||||||
String& name = String::Handle(zone);
|
String& name = String::Handle(zone);
|
||||||
if (FLAG_reify_generic_functions) {
|
const TypeArguments& type_params =
|
||||||
const TypeArguments& type_params =
|
TypeArguments::Handle(zone, type_parameters());
|
||||||
TypeArguments::Handle(zone, type_parameters());
|
if (!type_params.IsNull()) {
|
||||||
if (!type_params.IsNull()) {
|
const intptr_t num_type_params = type_params.Length();
|
||||||
const intptr_t num_type_params = type_params.Length();
|
ASSERT(num_type_params > 0);
|
||||||
ASSERT(num_type_params > 0);
|
TypeParameter& type_param = TypeParameter::Handle(zone);
|
||||||
TypeParameter& type_param = TypeParameter::Handle(zone);
|
AbstractType& bound = AbstractType::Handle(zone);
|
||||||
AbstractType& bound = AbstractType::Handle(zone);
|
pieces.Add(Symbols::LAngleBracket());
|
||||||
pieces.Add(Symbols::LAngleBracket());
|
for (intptr_t i = 0; i < num_type_params; i++) {
|
||||||
for (intptr_t i = 0; i < num_type_params; i++) {
|
type_param ^= type_params.TypeAt(i);
|
||||||
type_param ^= type_params.TypeAt(i);
|
name = type_param.name();
|
||||||
name = type_param.name();
|
pieces.Add(name);
|
||||||
|
bound = type_param.bound();
|
||||||
|
if (!bound.IsNull() && !bound.IsObjectType()) {
|
||||||
|
pieces.Add(Symbols::SpaceExtendsSpace());
|
||||||
|
name = bound.BuildName(name_visibility);
|
||||||
pieces.Add(name);
|
pieces.Add(name);
|
||||||
bound = type_param.bound();
|
|
||||||
if (!bound.IsNull() && !bound.IsObjectType()) {
|
|
||||||
pieces.Add(Symbols::SpaceExtendsSpace());
|
|
||||||
name = bound.BuildName(name_visibility);
|
|
||||||
pieces.Add(name);
|
|
||||||
}
|
|
||||||
if (i < num_type_params - 1) {
|
|
||||||
pieces.Add(Symbols::CommaSpace());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pieces.Add(Symbols::RAngleBracket());
|
if (i < num_type_params - 1) {
|
||||||
|
pieces.Add(Symbols::CommaSpace());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
pieces.Add(Symbols::RAngleBracket());
|
||||||
}
|
}
|
||||||
pieces.Add(Symbols::LParen());
|
pieces.Add(Symbols::LParen());
|
||||||
BuildSignatureParameters(thread, zone, name_visibility, &pieces);
|
BuildSignatureParameters(thread, zone, name_visibility, &pieces);
|
||||||
|
@ -16424,8 +16332,7 @@ bool Instance::IsInstanceOf(
|
||||||
other_instantiator_type_arguments, other_function_type_arguments,
|
other_instantiator_type_arguments, other_function_type_arguments,
|
||||||
kAllFree, bound_error, NULL, NULL, Heap::kOld);
|
kAllFree, bound_error, NULL, NULL, Heap::kOld);
|
||||||
if ((bound_error != NULL) && !bound_error->IsNull()) {
|
if ((bound_error != NULL) && !bound_error->IsNull()) {
|
||||||
ASSERT(Isolate::Current()->type_checks());
|
UNREACHABLE();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
if (instantiated_other.IsTypeRef()) {
|
if (instantiated_other.IsTypeRef()) {
|
||||||
instantiated_other = TypeRef::Cast(instantiated_other).type();
|
instantiated_other = TypeRef::Cast(instantiated_other).type();
|
||||||
|
@ -16435,8 +16342,7 @@ bool Instance::IsInstanceOf(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (FLAG_strong &&
|
if (IsFutureOrInstanceOf(zone, instantiated_other, bound_error)) {
|
||||||
IsFutureOrInstanceOf(zone, instantiated_other, bound_error)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!instantiated_other.IsFunctionType()) {
|
if (!instantiated_other.IsFunctionType()) {
|
||||||
|
@ -16472,7 +16378,7 @@ bool Instance::IsInstanceOf(
|
||||||
other_instantiator_type_arguments, other_function_type_arguments,
|
other_instantiator_type_arguments, other_function_type_arguments,
|
||||||
kAllFree, bound_error, NULL, NULL, Heap::kOld);
|
kAllFree, bound_error, NULL, NULL, Heap::kOld);
|
||||||
if ((bound_error != NULL) && !bound_error->IsNull()) {
|
if ((bound_error != NULL) && !bound_error->IsNull()) {
|
||||||
ASSERT(Isolate::Current()->type_checks());
|
UNREACHABLE();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (instantiated_other.IsTypeRef()) {
|
if (instantiated_other.IsTypeRef()) {
|
||||||
|
@ -16483,46 +16389,15 @@ bool Instance::IsInstanceOf(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
other_type_arguments = instantiated_other.arguments();
|
other_type_arguments = instantiated_other.arguments();
|
||||||
const bool other_is_dart_function = instantiated_other.IsDartFunctionType();
|
|
||||||
// In strong mode, subtyping rules of callable instances are restricted.
|
|
||||||
if (!FLAG_strong &&
|
|
||||||
(other_is_dart_function || instantiated_other.IsFunctionType())) {
|
|
||||||
// Check if this instance understands a call() method of a compatible type.
|
|
||||||
Function& sig_fun =
|
|
||||||
Function::Handle(zone, cls.LookupCallFunctionForTypeTest());
|
|
||||||
if (!sig_fun.IsNull()) {
|
|
||||||
if (other_is_dart_function) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!sig_fun.HasInstantiatedSignature(kCurrentClass)) {
|
|
||||||
// The following signature instantiation of sig_fun does not instantiate
|
|
||||||
// its own function type parameters, i.e there are 0 free function type
|
|
||||||
// params. Note that sig_fun has no generic parent, which is guaranteed
|
|
||||||
// to be the case, since the looked up call() function cannot be nested.
|
|
||||||
// It is most probably not even generic.
|
|
||||||
ASSERT(!sig_fun.HasGenericParent());
|
|
||||||
// No bound error possible, since the instance exists.
|
|
||||||
sig_fun = sig_fun.InstantiateSignatureFrom(
|
|
||||||
type_arguments, Object::null_type_arguments(), kNoneFree,
|
|
||||||
Heap::kOld);
|
|
||||||
}
|
|
||||||
const Function& other_signature =
|
|
||||||
Function::Handle(zone, Type::Cast(instantiated_other).signature());
|
|
||||||
if (sig_fun.IsSubtypeOf(other_signature, bound_error, NULL, Heap::kOld)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!instantiated_other.IsType()) {
|
if (!instantiated_other.IsType()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
other_class = instantiated_other.type_class();
|
other_class = instantiated_other.type_class();
|
||||||
if (IsNull()) {
|
if (IsNull()) {
|
||||||
ASSERT(cls.IsNullClass());
|
ASSERT(cls.IsNullClass());
|
||||||
// As of Dart 1.5, the null instance and Null type are handled differently.
|
// As of Dart 2.0, the null instance and Null type are handled differently.
|
||||||
// We already checked other for dynamic and void.
|
// We already checked other for dynamic and void.
|
||||||
if (FLAG_strong &&
|
if (IsFutureOrInstanceOf(zone, instantiated_other, bound_error)) {
|
||||||
IsFutureOrInstanceOf(zone, instantiated_other, bound_error)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return other_class.IsNullClass() || other_class.IsObjectClass();
|
return other_class.IsNullClass() || other_class.IsObjectClass();
|
||||||
|
@ -16534,7 +16409,6 @@ bool Instance::IsInstanceOf(
|
||||||
bool Instance::IsFutureOrInstanceOf(Zone* zone,
|
bool Instance::IsFutureOrInstanceOf(Zone* zone,
|
||||||
const AbstractType& other,
|
const AbstractType& other,
|
||||||
Error* bound_error) const {
|
Error* bound_error) const {
|
||||||
ASSERT(FLAG_strong);
|
|
||||||
if (other.IsType() &&
|
if (other.IsType() &&
|
||||||
Class::Handle(zone, other.type_class()).IsFutureOrClass()) {
|
Class::Handle(zone, other.type_class()).IsFutureOrClass()) {
|
||||||
if (other.arguments() == TypeArguments::null()) {
|
if (other.arguments() == TypeArguments::null()) {
|
||||||
|
@ -17091,10 +16965,6 @@ RawString* AbstractType::BuildName(NameVisibility name_visibility) const {
|
||||||
num_type_params = num_args;
|
num_type_params = num_args;
|
||||||
} else {
|
} else {
|
||||||
ASSERT(num_args == 0); // Type is raw.
|
ASSERT(num_args == 0); // Type is raw.
|
||||||
// No need to fill up with "dynamic", unless running in strong mode.
|
|
||||||
if (!FLAG_strong) {
|
|
||||||
num_type_params = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// The actual type argument vector can be longer than necessary, because
|
// The actual type argument vector can be longer than necessary, because
|
||||||
|
@ -17107,8 +16977,7 @@ RawString* AbstractType::BuildName(NameVisibility name_visibility) const {
|
||||||
}
|
}
|
||||||
GrowableHandlePtrArray<const String> pieces(zone, 4);
|
GrowableHandlePtrArray<const String> pieces(zone, 4);
|
||||||
pieces.Add(class_name);
|
pieces.Add(class_name);
|
||||||
if ((num_type_params == 0) ||
|
if (num_type_params == 0) {
|
||||||
(!FLAG_strong && args.IsRaw(first_type_param_index, num_type_params))) {
|
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
} else {
|
} else {
|
||||||
const String& args_name = String::Handle(
|
const String& args_name = String::Handle(
|
||||||
|
@ -17159,20 +17028,18 @@ bool AbstractType::IsTopType() const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// In strong mode, FutureOr<T> where T is a top type behaves as a top type.
|
// In strong mode, FutureOr<T> where T is a top type behaves as a top type.
|
||||||
if (FLAG_strong) {
|
Thread* thread = Thread::Current();
|
||||||
Thread* thread = Thread::Current();
|
Zone* zone = thread->zone();
|
||||||
Zone* zone = thread->zone();
|
if (Class::Handle(zone, type_class()).IsFutureOrClass()) {
|
||||||
if (Class::Handle(zone, type_class()).IsFutureOrClass()) {
|
if (arguments() == TypeArguments::null()) {
|
||||||
if (arguments() == TypeArguments::null()) {
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
const TypeArguments& type_arguments =
|
||||||
const TypeArguments& type_arguments =
|
TypeArguments::Handle(zone, arguments());
|
||||||
TypeArguments::Handle(zone, arguments());
|
const AbstractType& type_arg =
|
||||||
const AbstractType& type_arg =
|
AbstractType::Handle(zone, type_arguments.TypeAt(0));
|
||||||
AbstractType::Handle(zone, type_arguments.TypeAt(0));
|
if (type_arg.IsTopType()) {
|
||||||
if (type_arg.IsTopType()) {
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -17257,24 +17124,22 @@ bool AbstractType::TypeTest(TypeTestKind test_kind,
|
||||||
// However, in checked mode, a function type may include malbounded result
|
// However, in checked mode, a function type may include malbounded result
|
||||||
// type and/or malbounded parameter types, which will then be encountered here
|
// type and/or malbounded parameter types, which will then be encountered here
|
||||||
// at run time.
|
// at run time.
|
||||||
|
// TODO(regis): malformed types needs to be cleaned up as we won't be
|
||||||
|
// seeing any malformed types in the VM.
|
||||||
if (IsMalbounded()) {
|
if (IsMalbounded()) {
|
||||||
ASSERT(Isolate::Current()->type_checks());
|
|
||||||
if ((bound_error != NULL) && bound_error->IsNull()) {
|
if ((bound_error != NULL) && bound_error->IsNull()) {
|
||||||
*bound_error = error();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (other.IsMalbounded()) {
|
if (other.IsMalbounded()) {
|
||||||
ASSERT(Isolate::Current()->type_checks());
|
|
||||||
if ((bound_error != NULL) && bound_error->IsNull()) {
|
if ((bound_error != NULL) && bound_error->IsNull()) {
|
||||||
*bound_error = other.error();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Any type is a subtype of (and is more specific than) Object and dynamic.
|
// Any type is a subtype of (and is more specific than) Object and dynamic.
|
||||||
// As of Dart 1.24, void is dynamically treated like Object (except when
|
// As of Dart 2.0, the Null type is a subtype of (and is more specific than)
|
||||||
// comparing function-types).
|
|
||||||
// As of Dart 1.5, the Null type is a subtype of (and is more specific than)
|
|
||||||
// any type.
|
// any type.
|
||||||
if (other.IsTopType() || IsNullType()) {
|
if (other.IsTopType() || IsNullType()) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -17360,8 +17225,7 @@ bool AbstractType::TypeTest(TypeTestKind test_kind,
|
||||||
}
|
}
|
||||||
// In strong mode, check if 'other' is 'FutureOr'.
|
// In strong mode, check if 'other' is 'FutureOr'.
|
||||||
// If so, apply additional subtyping rules.
|
// If so, apply additional subtyping rules.
|
||||||
if (FLAG_strong &&
|
if (FutureOrTypeTest(zone, other, bound_error, bound_trail, space)) {
|
||||||
FutureOrTypeTest(zone, other, bound_error, bound_trail, space)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false; // TODO(regis): We should return "maybe after instantiation".
|
return false; // TODO(regis): We should return "maybe after instantiation".
|
||||||
|
@ -17386,28 +17250,6 @@ bool AbstractType::TypeTest(TypeTestKind test_kind,
|
||||||
return fun.TypeTest(test_kind, other_fun, bound_error, bound_trail,
|
return fun.TypeTest(test_kind, other_fun, bound_error, bound_trail,
|
||||||
space);
|
space);
|
||||||
}
|
}
|
||||||
// In strong mode, subtyping rules of callable instances are restricted.
|
|
||||||
if (!FLAG_strong) {
|
|
||||||
// Check if type S has a call() method of function type T.
|
|
||||||
const Function& call_function =
|
|
||||||
Function::Handle(zone, type_cls.LookupCallFunctionForTypeTest());
|
|
||||||
if (!call_function.IsNull()) {
|
|
||||||
if (other_is_dart_function_type) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// Shortcut the test involving the call function if the
|
|
||||||
// pair <this, other> is already in the trail.
|
|
||||||
if (TestAndAddBuddyToTrail(&bound_trail, other)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (call_function.TypeTest(
|
|
||||||
test_kind,
|
|
||||||
Function::Handle(zone, Type::Cast(other).signature()),
|
|
||||||
bound_error, bound_trail, space)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (other.IsFunctionType() && !other_type_cls.IsTypedefClass()) {
|
if (other.IsFunctionType() && !other_type_cls.IsTypedefClass()) {
|
||||||
// [this] is not a function type (and, in non-strong mode, does not
|
// [this] is not a function type (and, in non-strong mode, does not
|
||||||
// declare a compatible call() method as verified above). Therefore,
|
// declare a compatible call() method as verified above). Therefore,
|
||||||
|
@ -17425,8 +17267,7 @@ bool AbstractType::TypeTest(TypeTestKind test_kind,
|
||||||
if (IsFunctionType()) {
|
if (IsFunctionType()) {
|
||||||
// In strong mode, check if 'other' is 'FutureOr'.
|
// In strong mode, check if 'other' is 'FutureOr'.
|
||||||
// If so, apply additional subtyping rules.
|
// If so, apply additional subtyping rules.
|
||||||
if (FLAG_strong &&
|
if (FutureOrTypeTest(zone, other, bound_error, bound_trail, space)) {
|
||||||
FutureOrTypeTest(zone, other, bound_error, bound_trail, space)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -17444,7 +17285,6 @@ bool AbstractType::FutureOrTypeTest(Zone* zone,
|
||||||
Heap::Space space) const {
|
Heap::Space space) const {
|
||||||
// In strong mode, there is no difference between 'is subtype of' and
|
// In strong mode, there is no difference between 'is subtype of' and
|
||||||
// 'is more specific than'.
|
// 'is more specific than'.
|
||||||
ASSERT(FLAG_strong);
|
|
||||||
if (other.IsType() &&
|
if (other.IsType() &&
|
||||||
Class::Handle(zone, other.type_class()).IsFutureOrClass()) {
|
Class::Handle(zone, other.type_class()).IsFutureOrClass()) {
|
||||||
if (other.arguments() == TypeArguments::null()) {
|
if (other.arguments() == TypeArguments::null()) {
|
||||||
|
@ -17611,18 +17451,7 @@ bool Type::IsMalformed() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Type::IsMalbounded() const {
|
bool Type::IsMalbounded() const {
|
||||||
if (raw_ptr()->sig_or_err_.error_ == LanguageError::null()) {
|
return false;
|
||||||
return false; // Valid type, but not a function type.
|
|
||||||
}
|
|
||||||
if (!Isolate::Current()->type_checks()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!raw_ptr()->sig_or_err_.error_->IsLanguageError()) {
|
|
||||||
return false; // Valid function type.
|
|
||||||
}
|
|
||||||
const LanguageError& type_error = LanguageError::Handle(error());
|
|
||||||
ASSERT(!type_error.IsNull());
|
|
||||||
return type_error.kind() == Report::kMalboundedType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Type::IsMalformedOrMalbounded() const {
|
bool Type::IsMalformedOrMalbounded() const {
|
||||||
|
@ -17637,7 +17466,7 @@ bool Type::IsMalformedOrMalbounded() const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
ASSERT(type_error.kind() == Report::kMalboundedType);
|
ASSERT(type_error.kind() == Report::kMalboundedType);
|
||||||
return Isolate::Current()->type_checks();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
RawLanguageError* Type::error() const {
|
RawLanguageError* Type::error() const {
|
||||||
|
@ -17895,12 +17724,10 @@ bool Type::IsEquivalent(const Instance& other, TrailPtr trail) const {
|
||||||
const Function& other_sig_fun =
|
const Function& other_sig_fun =
|
||||||
Function::Handle(zone, other_type.signature());
|
Function::Handle(zone, other_type.signature());
|
||||||
|
|
||||||
if (FLAG_reify_generic_functions) {
|
// Compare function type parameters and their bounds.
|
||||||
// Compare function type parameters and their bounds.
|
// Check the type parameters and bounds of generic functions.
|
||||||
// Check the type parameters and bounds of generic functions.
|
if (!sig_fun.HasSameTypeParametersAndBounds(other_sig_fun)) {
|
||||||
if (!sig_fun.HasSameTypeParametersAndBounds(other_sig_fun)) {
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare number of function parameters.
|
// Compare number of function parameters.
|
||||||
|
@ -19035,58 +18862,6 @@ RawAbstractType* BoundedType::InstantiateFrom(
|
||||||
// (or instantiated) either.
|
// (or instantiated) either.
|
||||||
// Note that instantiator_type_arguments must have the final length, though.
|
// Note that instantiator_type_arguments must have the final length, though.
|
||||||
}
|
}
|
||||||
// If instantiated_bounded_type is not finalized, it is too early to check
|
|
||||||
// its upper bound. It will be checked in a second finalization phase.
|
|
||||||
if ((Isolate::Current()->type_checks()) && (bound_error != NULL) &&
|
|
||||||
bound_error->IsNull() && instantiated_bounded_type.IsFinalized()) {
|
|
||||||
AbstractType& upper_bound = AbstractType::Handle(bound());
|
|
||||||
ASSERT(!upper_bound.IsObjectType() && !upper_bound.IsDynamicType());
|
|
||||||
AbstractType& instantiated_upper_bound =
|
|
||||||
AbstractType::Handle(upper_bound.raw());
|
|
||||||
if (upper_bound.IsFinalized() &&
|
|
||||||
!upper_bound.IsInstantiated(kAny, num_free_fun_type_params)) {
|
|
||||||
instantiated_upper_bound = upper_bound.InstantiateFrom(
|
|
||||||
instantiator_type_arguments, function_type_arguments,
|
|
||||||
num_free_fun_type_params, bound_error, instantiation_trail,
|
|
||||||
bound_trail, space);
|
|
||||||
// The instantiated_upper_bound may not be finalized or instantiated.
|
|
||||||
// See comment above.
|
|
||||||
}
|
|
||||||
if (bound_error->IsNull()) {
|
|
||||||
// Shortcut the F-bounded case where we have reached a fixpoint.
|
|
||||||
if (instantiated_bounded_type.Equals(bounded_type) &&
|
|
||||||
instantiated_upper_bound.Equals(upper_bound)) {
|
|
||||||
return bounded_type.raw();
|
|
||||||
}
|
|
||||||
const TypeParameter& type_param = TypeParameter::Handle(type_parameter());
|
|
||||||
if (instantiated_upper_bound.IsFinalized() &&
|
|
||||||
(!type_param.CheckBound(instantiated_bounded_type,
|
|
||||||
instantiated_upper_bound, bound_error,
|
|
||||||
bound_trail, space) &&
|
|
||||||
bound_error->IsNull())) {
|
|
||||||
// We cannot determine yet whether the bounded_type is below the
|
|
||||||
// upper_bound, because one or both of them is still being finalized or
|
|
||||||
// uninstantiated. For example, instantiated_bounded_type may be the
|
|
||||||
// still unfinalized cloned type parameter of a mixin application class.
|
|
||||||
// There is another special case where we do not want to report a bound
|
|
||||||
// error yet: if the upper bound is a function type, but the bounded
|
|
||||||
// type is not and its class is not compiled yet, i.e. we cannot look
|
|
||||||
// for a call method yet.
|
|
||||||
ASSERT(!instantiated_bounded_type.IsInstantiated() ||
|
|
||||||
!instantiated_upper_bound.IsInstantiated() ||
|
|
||||||
(!instantiated_bounded_type.IsFunctionType() &&
|
|
||||||
instantiated_upper_bound.IsFunctionType() &&
|
|
||||||
instantiated_bounded_type.HasTypeClass() &&
|
|
||||||
!Class::Handle(instantiated_bounded_type.type_class())
|
|
||||||
.is_finalized()));
|
|
||||||
// Postpone bound check by returning a new BoundedType with unfinalized
|
|
||||||
// or partially instantiated bounded_type and upper_bound, but keeping
|
|
||||||
// type_param.
|
|
||||||
instantiated_bounded_type = BoundedType::New(
|
|
||||||
instantiated_bounded_type, instantiated_upper_bound, type_param);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return instantiated_bounded_type.raw();
|
return instantiated_bounded_type.raw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1087,7 +1087,6 @@ class Class : public Object {
|
||||||
RawFunction* LookupFunctionAllowPrivate(const String& name) const;
|
RawFunction* LookupFunctionAllowPrivate(const String& name) const;
|
||||||
RawFunction* LookupGetterFunction(const String& name) const;
|
RawFunction* LookupGetterFunction(const String& name) const;
|
||||||
RawFunction* LookupSetterFunction(const String& name) const;
|
RawFunction* LookupSetterFunction(const String& name) const;
|
||||||
RawFunction* LookupCallFunctionForTypeTest() const;
|
|
||||||
RawField* LookupInstanceField(const String& name) const;
|
RawField* LookupInstanceField(const String& name) const;
|
||||||
RawField* LookupStaticField(const String& name) const;
|
RawField* LookupStaticField(const String& name) const;
|
||||||
RawField* LookupField(const String& name) const;
|
RawField* LookupField(const String& name) const;
|
||||||
|
@ -2493,14 +2492,11 @@ class Function : public Object {
|
||||||
bool IsInFactoryScope() const;
|
bool IsInFactoryScope() const;
|
||||||
|
|
||||||
bool NeedsArgumentTypeChecks(Isolate* I) const {
|
bool NeedsArgumentTypeChecks(Isolate* I) const {
|
||||||
if (FLAG_strong) {
|
if (!I->should_emit_strong_mode_checks()) {
|
||||||
if (!I->should_emit_strong_mode_checks()) {
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return IsClosureFunction() ||
|
|
||||||
!(is_static() || (kind() == RawFunction::kConstructor));
|
|
||||||
}
|
}
|
||||||
return I->type_checks();
|
return IsClosureFunction() ||
|
||||||
|
!(is_static() || (kind() == RawFunction::kConstructor));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MayHaveUncheckedEntryPoint(Isolate* I) const;
|
bool MayHaveUncheckedEntryPoint(Isolate* I) const;
|
||||||
|
|
|
@ -74,8 +74,7 @@ ParsedFunction::ParsedFunction(Thread* thread, const Function& function)
|
||||||
Symbols::CurrentContextVar(), Object::dynamic_type());
|
Symbols::CurrentContextVar(), Object::dynamic_type());
|
||||||
current_context_var_ = temp;
|
current_context_var_ = temp;
|
||||||
|
|
||||||
const bool reify_generic_argument =
|
const bool reify_generic_argument = function.IsGeneric();
|
||||||
function.IsGeneric() && FLAG_reify_generic_functions;
|
|
||||||
|
|
||||||
const bool load_optional_arguments = function.HasOptionalParameters();
|
const bool load_optional_arguments = function.HasOptionalParameters();
|
||||||
|
|
||||||
|
|
|
@ -366,24 +366,8 @@ DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 3) {
|
||||||
// Code inlined in the caller should have optimized the case where the
|
// Code inlined in the caller should have optimized the case where the
|
||||||
// instantiator can be reused as type argument vector.
|
// instantiator can be reused as type argument vector.
|
||||||
ASSERT(!type_arguments.IsUninstantiatedIdentity());
|
ASSERT(!type_arguments.IsUninstantiatedIdentity());
|
||||||
if (isolate->type_checks()) {
|
type_arguments = type_arguments.InstantiateAndCanonicalizeFrom(
|
||||||
Error& bound_error = Error::Handle(zone);
|
instantiator_type_arguments, function_type_arguments, NULL);
|
||||||
type_arguments = type_arguments.InstantiateAndCanonicalizeFrom(
|
|
||||||
instantiator_type_arguments, function_type_arguments, &bound_error);
|
|
||||||
if (!bound_error.IsNull()) {
|
|
||||||
// Throw a dynamic type error.
|
|
||||||
const TokenPosition location = GetCallerLocation();
|
|
||||||
String& bound_error_message =
|
|
||||||
String::Handle(zone, String::New(bound_error.ToErrorCString()));
|
|
||||||
Exceptions::CreateAndThrowTypeError(
|
|
||||||
location, AbstractType::Handle(zone), AbstractType::Handle(zone),
|
|
||||||
Symbols::Empty(), bound_error_message);
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
type_arguments = type_arguments.InstantiateAndCanonicalizeFrom(
|
|
||||||
instantiator_type_arguments, function_type_arguments, NULL);
|
|
||||||
}
|
|
||||||
ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated());
|
ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated());
|
||||||
arguments.SetReturn(type_arguments);
|
arguments.SetReturn(type_arguments);
|
||||||
}
|
}
|
||||||
|
@ -833,8 +817,7 @@ DEFINE_RUNTIME_ENTRY(TypeCheck, 7) {
|
||||||
}
|
}
|
||||||
String& bound_error_message = String::Handle(zone);
|
String& bound_error_message = String::Handle(zone);
|
||||||
if (!bound_error.IsNull()) {
|
if (!bound_error.IsNull()) {
|
||||||
ASSERT(isolate->type_checks());
|
UNREACHABLE();
|
||||||
bound_error_message = String::New(bound_error.ToErrorCString());
|
|
||||||
}
|
}
|
||||||
if (dst_name.IsNull()) {
|
if (dst_name.IsNull()) {
|
||||||
#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32)
|
#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32)
|
||||||
|
|
|
@ -191,8 +191,7 @@ class SimulatorHelpers {
|
||||||
static bool ObjectArraySetIndexed(Thread* thread,
|
static bool ObjectArraySetIndexed(Thread* thread,
|
||||||
RawObject** FP,
|
RawObject** FP,
|
||||||
RawObject** result) {
|
RawObject** result) {
|
||||||
return !thread->isolate()->type_checks() &&
|
return ObjectArraySetIndexedUnchecked(thread, FP, result);
|
||||||
ObjectArraySetIndexedUnchecked(thread, FP, result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ObjectArraySetIndexedUnchecked(Thread* thread,
|
static bool ObjectArraySetIndexedUnchecked(Thread* thread,
|
||||||
|
@ -225,8 +224,7 @@ class SimulatorHelpers {
|
||||||
static bool GrowableArraySetIndexed(Thread* thread,
|
static bool GrowableArraySetIndexed(Thread* thread,
|
||||||
RawObject** FP,
|
RawObject** FP,
|
||||||
RawObject** result) {
|
RawObject** result) {
|
||||||
return !thread->isolate()->type_checks() &&
|
return GrowableArraySetIndexedUnchecked(thread, FP, result);
|
||||||
GrowableArraySetIndexedUnchecked(thread, FP, result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool GrowableArraySetIndexedUnchecked(Thread* thread,
|
static bool GrowableArraySetIndexedUnchecked(Thread* thread,
|
||||||
|
|
|
@ -4,9 +4,6 @@
|
||||||
# Sections in this file should contain "$runtime == flutter".
|
# Sections in this file should contain "$runtime == flutter".
|
||||||
# What tests does this comment apply to? Please add it to each test's line
|
# What tests does this comment apply to? Please add it to each test's line
|
||||||
# or file an issue an put it there, and add the issue to the relevant tests:
|
# or file an issue an put it there, and add the issue to the relevant tests:
|
||||||
# flutter uses --error_on_bad_type and --await_is_keyword so the following tests
|
|
||||||
# fail with a Compilation Error.
|
|
||||||
# Note that --error_on_bad_override is ignored in strong mode.
|
|
||||||
|
|
||||||
[ $runtime == flutter ]
|
[ $runtime == flutter ]
|
||||||
async_await_syntax_test/a05c: CompileTimeError
|
async_await_syntax_test/a05c: CompileTimeError
|
||||||
|
|
Loading…
Reference in a new issue