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:
asiva 2018-11-20 17:25:42 +00:00 committed by Siva Annamalai
parent b0730135ff
commit 0ca1c57593
48 changed files with 192 additions and 925 deletions

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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);
} }

View file

@ -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();

View file

@ -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,

View file

@ -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

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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,

View file

@ -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);

View file

@ -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());

View file

@ -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());

View file

@ -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);

View file

@ -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());

View file

@ -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());

View file

@ -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:

View file

@ -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);

View file

@ -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);

View file

@ -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();
} }

View file

@ -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);
} }
} }

View file

@ -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);

View file

@ -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());
} }
} }

View file

@ -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;
} }

View file

@ -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();

View file

@ -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_);
} }

View file

@ -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);

View file

@ -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());

View file

@ -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( \

View file

@ -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);

View file

@ -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,

View file

@ -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)

View file

@ -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.") \

View file

@ -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,

View file

@ -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

View file

@ -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);

View file

@ -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();

View file

@ -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

View file

@ -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)

View file

@ -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++;
} }

View file

@ -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();
} }

View file

@ -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;

View file

@ -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();

View file

@ -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)

View file

@ -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,

View file

@ -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