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;
try {
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);
process = await StdioProcess.run(context.vm.toFilePath(), args);
print(process.output);

View file

@ -553,13 +553,11 @@ typedef struct {
* for each part.
*/
#define DART_FLAGS_CURRENT_VERSION (0x00000009)
#define DART_FLAGS_CURRENT_VERSION (0x0000000a)
typedef struct {
int32_t version;
bool enable_type_checks;
bool enable_asserts;
bool enable_error_on_bad_type;
bool use_field_guards;
bool use_osr;
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
// checked mode.
if (!checked.IsNull()) {
bool is_checked = checked.value();
Dart_IsolateFlags* flags = state->isolate_flags();
flags->enable_asserts = is_checked;
// Do not enable type checks in strong mode.
flags->enable_type_checks = is_checked && !FLAG_strong;
flags->enable_asserts = checked.value();
}
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));
Class& interface_cls = Class::Handle(zone);
intptr_t num_type_args = 0; // Remains 0 when executing Dart 1.0 code.
// TODO(regis): Check for strong mode too?
if (FLAG_reify_generic_functions) {
const TypeArguments& function_type_args =
TypeArguments::Handle(zone, arguments->NativeTypeArgs());
if (function_type_args.Length() == 1) {
const AbstractType& function_type_arg =
AbstractType::Handle(zone, function_type_args.TypeAt(0));
if (function_type_arg.IsType() &&
(function_type_arg.arguments() == TypeArguments::null())) {
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")));
intptr_t num_type_args = 0;
const TypeArguments& function_type_args =
TypeArguments::Handle(zone, arguments->NativeTypeArgs());
if (function_type_args.Length() == 1) {
const AbstractType& function_type_arg =
AbstractType::Handle(zone, function_type_args.TypeAt(0));
if (function_type_arg.IsType() &&
(function_type_arg.arguments() == TypeArguments::null())) {
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 (instance.IsNull()) {
Exceptions::ThrowArgumentError(instance);
}

View file

@ -23,7 +23,6 @@
namespace dart {
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_type_finalization, false, "Trace type finalization.");
@ -485,12 +484,6 @@ void ClassFinalizer::ResolveTypeClass(const Class& cls, const Type& type) {
}
ASSERT(!type_class.IsTypedefClass() ||
(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) {
@ -708,26 +701,15 @@ intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments(
// The class has num_type_parameters type parameters.
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.
// Check the number of parsed type arguments, if any.
// 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.
TypeArguments& arguments = TypeArguments::Handle(zone, type.arguments());
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.
// A static warning should have been reported.
// TODO(regis): Check if this is dead code.
arguments = TypeArguments::null();
type.set_arguments(arguments);
}
@ -743,7 +725,7 @@ intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments(
// super types of type_class, which are initialized from the parsed
// type arguments, followed by the parsed type arguments.
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
// type arguments to the vector, we can leave the vector as null.
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,
const AbstractType& type,
FinalizationKind finalization,
@ -1149,9 +975,6 @@ RawAbstractType* ClassFinalizer::FinalizeType(const Class& cls,
// malformed.
if ((finalization >= kCanonicalize) && !type.IsMalformed() &&
!type.IsCanonical() && type.IsType()) {
if (!FLAG_strong) {
CheckTypeBounds(cls, type);
}
return type.Canonicalize();
}
return type.raw();
@ -1291,17 +1114,6 @@ RawAbstractType* ClassFinalizer::FinalizeType(const Class& cls,
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) {
THR_Print("Done finalizing type '%s' with %" Pd " type args: %s\n",
String::Handle(zone, type.Name()).ToCString(),
@ -1507,7 +1319,7 @@ void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) {
Field& field = Field::Handle(zone);
AbstractType& type = AbstractType::Handle(zone);
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++) {
field ^= array.At(i);
type = field.type();
@ -2747,12 +2559,7 @@ void ClassFinalizer::CollectTypeArguments(
}
return;
}
if (Isolate::Current()->error_on_bad_type()) {
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());
}
// TODO(regis): Check if this is dead code.
// Discard provided type arguments and treat type as raw.
}
// Fill arguments with type dynamic.
@ -3216,9 +3023,6 @@ void ClassFinalizer::MarkTypeMalformed(const Error& prev_error,
LanguageError& error = LanguageError::Handle(LanguageError::NewFormattedV(
prev_error, script, type.token_pos(), Report::AtLocation,
Report::kMalformedType, Heap::kOld, format, args));
if (Isolate::Current()->error_on_bad_type()) {
ReportError(error);
}
type.set_error(error);
// Make the type raw, since it may not be possible to
// properly finalize its type arguments.
@ -3274,9 +3078,6 @@ void ClassFinalizer::FinalizeMalboundedType(const Error& prev_error,
prev_error, script, type.token_pos(), Report::AtLocation,
Report::kMalboundedType, Heap::kOld, format, args));
va_end(args);
if (Isolate::Current()->error_on_bad_type()) {
ReportError(error);
}
type.set_error(error);
if (!type.IsFinalized()) {
type.SetIsFinalized();

View file

@ -152,10 +152,6 @@ class ClassFinalizer : public AllStatic {
static void CheckRecursiveType(const Class& cls,
const AbstractType& type,
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 FinalizeUpperBounds(
const Class& cls,

View file

@ -1111,10 +1111,7 @@ void FlowGraph::PopulateEnvironmentFromFunctionEntry(
// Check if inlining_parameters include a type argument vector parameter.
const intptr_t inlined_type_args_param =
(FLAG_reify_generic_functions && (inlining_parameters != NULL) &&
function().IsGeneric())
? 1
: 0;
((inlining_parameters != NULL) && function().IsGeneric()) ? 1 : 0;
for (intptr_t i = 0; i < parameter_count; i++) {
ParameterInstr* param = new (zone()) ParameterInstr(i, function_entry);
@ -1139,11 +1136,9 @@ void FlowGraph::PopulateEnvironmentFromFunctionEntry(
}
// Replace the type arguments slot with a special parameter.
const bool reify_generic_argument =
function().IsGeneric() && FLAG_reify_generic_functions;
const bool reify_generic_argument = function().IsGeneric();
if (reify_generic_argument) {
ASSERT(parsed_function().function_type_arguments() != NULL);
Definition* defn;
if (inlining_parameters == NULL) {
// Note: If we are not inlining, then the prologue builder will

View file

@ -492,7 +492,7 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest(
}
if (type.IsType()) {
// 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);
}
__ ldm(IA, SP,
@ -1154,8 +1154,7 @@ void FlowGraphCompiler::EmitOptimizedStaticCall(
LocationSummary* locs,
Code::EntryKind entry_kind) {
ASSERT(!function.IsClosureFunction());
if (function.HasOptionalParameters() ||
(FLAG_reify_generic_functions && function.IsGeneric())) {
if (function.HasOptionalParameters() || function.IsGeneric()) {
__ LoadObject(R4, arguments_descriptor);
} else {
__ LoadImmediate(R4, 0); // GC safe smi zero because of stub.

View file

@ -478,7 +478,7 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest(
}
if (type.IsType()) {
// 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);
}
__ ldp(kFunctionTypeArgumentsReg, kInstantiatorTypeArgumentsReg,
@ -1136,8 +1136,7 @@ void FlowGraphCompiler::EmitOptimizedStaticCall(
Code::EntryKind entry_kind) {
// TODO(sjindel/entrypoints): Support multiple entrypoints on ARM64.
ASSERT(!function.IsClosureFunction());
if (function.HasOptionalParameters() ||
(FLAG_reify_generic_functions && function.IsGeneric())) {
if (function.HasOptionalParameters() || function.IsGeneric()) {
__ LoadObject(R4, arguments_descriptor);
} else {
__ LoadImmediate(R4, 0); // GC safe smi zero because of stub.

View file

@ -498,7 +498,7 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest(
}
if (type.IsType()) {
// 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?
__ j(ZERO, is_not_instance_lbl);
}
@ -1008,8 +1008,7 @@ void FlowGraphCompiler::EmitOptimizedStaticCall(
LocationSummary* locs,
Code::EntryKind entry_kind) {
// TODO(sjindel/entrypoints): Support multiple entrypoints on IA32.
if (function.HasOptionalParameters() ||
(FLAG_reify_generic_functions && function.IsGeneric())) {
if (function.HasOptionalParameters() || function.IsGeneric()) {
__ LoadObject(EDX, arguments_descriptor);
} else {
__ xorl(EDX, EDX); // GC safe smi zero because of stub.

View file

@ -504,7 +504,7 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest(
}
if (type.IsType()) {
// 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?
__ j(ZERO, is_not_instance_lbl);
}
@ -1131,8 +1131,7 @@ void FlowGraphCompiler::EmitOptimizedStaticCall(
LocationSummary* locs,
Code::EntryKind entry_kind) {
ASSERT(!function.IsClosureFunction());
if (function.HasOptionalParameters() ||
(FLAG_reify_generic_functions && function.IsGeneric())) {
if (function.HasOptionalParameters() || function.IsGeneric()) {
__ LoadObject(R10, arguments_descriptor);
} else {
__ 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
// 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();
}
}
@ -2781,7 +2781,7 @@ Definition* AssertAssignableInstr::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,

View file

@ -2929,7 +2929,7 @@ class AssertAssignableInstr : public TemplateDefinition<3, Throws, Pure> {
ASSERT(!dst_type.IsNull());
ASSERT(!dst_type.IsTypeRef());
ASSERT(!dst_name.IsNull());
ASSERT(!FLAG_strong || !dst_type.IsDynamicType());
ASSERT(!dst_type.IsDynamicType());
SetInputAt(0, value);
SetInputAt(1, instantiator_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(); }
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();
// Write barrier is skipped for nullable and non-nullable smis.
ASSERT(cid != kSmiCid);
@ -4387,13 +4380,6 @@ class StoreStaticFieldInstr : public TemplateDefinition<1, NoThrow> {
private:
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();
// Write barrier is skipped for nullable and non-nullable smis.
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.
ASSERT(locs->always_calls());
Label done;
Isolate* isolate = Isolate::Current();
if (isolate->type_checks()) {
__ CompareObject(reg, Bool::True());
__ b(&done, EQ);
__ CompareObject(reg, Bool::False());
__ b(&done, EQ);
} else {
ASSERT(isolate->asserts() || FLAG_strong);
__ CompareObject(reg, Object::null_instance());
__ b(&done, NE);
}
__ CompareObject(reg, Object::null_instance());
__ b(&done, NE);
__ Push(reg); // Push the source object.
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.
ASSERT(ArgumentCount() ==
function().NumParameters() +
(function().IsGeneric() && FLAG_reify_generic_functions)
? 1
: 0);
function().NumParameters() + (function().IsGeneric() ? 1 : 0));
// Push the result place holder initialized to NULL.
__ 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.
ASSERT(locs->always_calls());
Label done;
Isolate* isolate = Isolate::Current();
if (isolate->type_checks()) {
__ CompareObject(reg, Bool::True());
__ b(&done, EQ);
__ CompareObject(reg, Bool::False());
__ b(&done, EQ);
} else {
ASSERT(isolate->asserts() || FLAG_strong);
__ CompareObject(reg, Object::null_instance());
__ b(&done, NE);
}
__ CompareObject(reg, Object::null_instance());
__ b(&done, NE);
__ Push(reg); // Push the source object.
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.
ASSERT(ArgumentCount() ==
function().NumParameters() +
(function().IsGeneric() && FLAG_reify_generic_functions)
? 1
: 0);
function().NumParameters() + (function().IsGeneric() ? 1 : 0));
// Push the result place holder initialized to NULL.
__ PushObject(Object::null_object());

View file

@ -199,8 +199,7 @@ EMIT_NATIVE_CODE(AssertBoolean,
if (compiler->is_optimizing()) {
__ Push(locs()->in(0).reg());
}
Isolate* isolate = Isolate::Current();
__ AssertBoolean(isolate->type_checks() ? 1 : 0);
__ AssertBoolean(0);
compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
token_pos());
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.
ASSERT(locs->always_calls());
Label done;
Isolate* isolate = Isolate::Current();
if (isolate->type_checks()) {
__ CompareObject(reg, Bool::True());
__ 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);
}
__ CompareObject(reg, Object::null_instance());
__ j(NOT_EQUAL, &done, Assembler::kNearJump);
__ pushl(reg); // Push the source object.
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.
ASSERT(ArgumentCount() ==
function().NumParameters() +
(function().IsGeneric() && FLAG_reify_generic_functions)
? 1
: 0);
function().NumParameters() + (function().IsGeneric() ? 1 : 0));
// Push the result place holder initialized to NULL.
__ 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.
ASSERT(locs->always_calls());
Label done;
Isolate* isolate = Isolate::Current();
if (isolate->type_checks()) {
__ CompareObject(reg, Bool::True());
__ 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);
}
__ CompareObject(reg, Object::null_instance());
__ j(NOT_EQUAL, &done, Assembler::kNearJump);
__ pushq(reg); // Push the source object.
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.
ASSERT(ArgumentCount() ==
function().NumParameters() +
(function().IsGeneric() && FLAG_reify_generic_functions)
? 1
: 0);
function().NumParameters() + (function().IsGeneric() ? 1 : 0));
// Push the result place holder initialized to NULL.
__ PushObject(Object::null_object());

View file

@ -1049,8 +1049,7 @@ class CallSiteInliner : public ValueObject {
// without linking between the caller and callee graphs.
// 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 inlined_type_args_param =
(FLAG_reify_generic_functions && function.IsGeneric()) ? 1 : 0;
const intptr_t inlined_type_args_param = function.IsGeneric() ? 1 : 0;
const intptr_t num_inlined_params =
inlined_type_args_param + function.NumParameters();
ZoneGrowableArray<Definition*>* param_stubs =
@ -3028,7 +3027,6 @@ static bool InlineByteArrayBaseStore(FlowGraph* flow_graph,
cursor =
flow_graph->AppendTo(cursor, check, call->env(), FlowGraph::kEffect);
// With an explicit null check, a non-speculative unbox suffices.
ASSERT(FLAG_strong);
switch (view_cid) {
case kTypedDataFloat32ArrayCid:
case kTypedDataFloat64ArrayCid:

View file

@ -761,11 +761,7 @@ const AbstractType* CompileType::ToAbstractType() {
Isolate* I = Isolate::Current();
const Class& type_class = Class::Handle(I->class_table()->At(cid_));
if (type_class.NumTypeArguments() > 0) {
if (FLAG_strong) {
type_ = &AbstractType::ZoneHandle(type_class.RareType());
} else {
type_ = &Object::dynamic_type();
}
type_ = &AbstractType::ZoneHandle(type_class.RareType());
} else {
type_ = &Type::ZoneHandle(Type::NewNonParameterizedType(type_class));
}
@ -1215,8 +1211,7 @@ CompileType StaticCallInstr::ComputeType() const {
return CompileType::FromCid(MethodRecognizer::ResultCid(function_));
}
const Isolate* isolate = Isolate::Current();
if (isolate->can_use_strong_mode_types() || isolate->type_checks()) {
if (Isolate::Current()->can_use_strong_mode_types()) {
const AbstractType& result_type =
AbstractType::ZoneHandle(function().result_type());
// TODO(dartbug.com/30480): instantiate generic result_type if possible.
@ -1234,8 +1229,7 @@ CompileType StaticCallInstr::ComputeType() const {
}
CompileType LoadLocalInstr::ComputeType() const {
const Isolate* isolate = Isolate::Current();
if (isolate->can_use_strong_mode_types() || isolate->type_checks()) {
if (Isolate::Current()->can_use_strong_mode_types()) {
const AbstractType& local_type = local().type();
TraceStrongModeType(this, local_type);
return CompileType::FromAbstractType(local_type);
@ -1270,8 +1264,7 @@ CompileType LoadStaticFieldInstr::ComputeType() const {
intptr_t cid = kDynamicCid;
AbstractType* abstract_type = NULL;
const Field& field = this->StaticField();
const Isolate* isolate = Isolate::Current();
if (isolate->can_use_strong_mode_types() || isolate->type_checks()) {
if (Isolate::Current()->can_use_strong_mode_types()) {
cid = kIllegalCid; // Abstract type is known, calculate cid lazily.
abstract_type = &AbstractType::ZoneHandle(field.type());
TraceStrongModeType(this, *abstract_type);
@ -1329,8 +1322,7 @@ CompileType LoadFieldInstr::ComputeType() const {
intptr_t cid = kDynamicCid;
const AbstractType* abstract_type = NULL;
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.
abstract_type = &field_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
// not in strong mode or if at a dynamic invocation.
bool needs_check = true;
if (FLAG_strong && !instr->interface_target().IsNull() &&
(field.kernel_offset() >= 0)) {
if (!instr->interface_target().IsNull() && (field.kernel_offset() >= 0)) {
bool is_covariant = false;
bool is_generic_covariant = false;
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 should never end up evaluating constants using the VM's constant
// evaluator.
if (FLAG_strong && FLAG_precompiled_mode) {
if (FLAG_precompiled_mode) {
UNREACHABLE();
}
@ -954,7 +954,7 @@ RawObject* ConstantEvaluator::EvaluateConstConstructorCall(
// 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
// evaluator.
if (FLAG_strong && FLAG_precompiled_mode) {
if (FLAG_precompiled_mode) {
UNREACHABLE();
}

View file

@ -432,7 +432,7 @@ Fragment StreamingFlowGraphBuilder::BuildInitializers(
Fragment StreamingFlowGraphBuilder::BuildDefaultTypeHandling(
const Function& function,
intptr_t type_parameters_offset) {
if (function.IsGeneric() && FLAG_reify_generic_functions) {
if (function.IsGeneric()) {
AlternativeReadingScope alt(&reader_);
SetOffset(type_parameters_offset);
intptr_t num_type_params = ReadListLength();
@ -554,7 +554,7 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfImplicitClosureFunction(
FunctionNodeHelper::kPositionalParameters);
intptr_t type_args_len = 0;
if (function.IsGeneric() && FLAG_reify_generic_functions) {
if (function.IsGeneric()) {
type_args_len = function.NumTypeParameters();
ASSERT(parsed_function()->function_type_arguments() != NULL);
body += LoadLocal(parsed_function()->function_type_arguments());
@ -720,7 +720,7 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfNoSuchMethodForwarder(
body += IntConstant(0);
body += StoreLocal(TokenPosition::kNoSource, argument_count_var);
body += Drop();
if (function.IsGeneric() && FLAG_reify_generic_functions) {
if (function.IsGeneric()) {
Fragment then;
Fragment otherwise;
otherwise += IntConstant(1);
@ -769,7 +769,7 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfNoSuchMethodForwarder(
// arguments[0] = function_type_arguments;
// i = 1;
// }
if (function.IsGeneric() && FLAG_reify_generic_functions) {
if (function.IsGeneric()) {
Fragment store;
store += LoadLocal(arguments);
store += IntConstant(0);
@ -983,9 +983,6 @@ void StreamingFlowGraphBuilder::BuildArgumentTypeChecks(
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);
Fragment check_bounds;
for (intptr_t i = 0; i < num_type_params; ++i) {
@ -995,10 +992,6 @@ void StreamingFlowGraphBuilder::BuildArgumentTypeChecks(
AbstractType& bound = T.BuildType(); // read bound
helper.Finish();
if (!has_reified_type_arguments) {
continue;
}
if (forwarding_target != NULL) {
forwarding_param ^= forwarding_params.TypeAt(i);
bound = forwarding_param.bound();
@ -1137,8 +1130,6 @@ void StreamingFlowGraphBuilder::BuildArgumentTypeChecks(
}
Fragment StreamingFlowGraphBuilder::PushAllArguments(PushedArguments* pushed) {
ASSERT(FLAG_strong);
FunctionNodeHelper function_node_helper(this);
function_node_helper.SetNext(FunctionNodeHelper::kTypeParameters);
@ -1152,11 +1143,9 @@ Fragment StreamingFlowGraphBuilder::PushAllArguments(PushedArguments* pushed) {
helper.Finish();
}
if (FLAG_reify_generic_functions) {
body += LoadLocal(parsed_function()->function_type_arguments());
body += PushArgument();
pushed->type_args_len = num_type_params;
}
body += LoadLocal(parsed_function()->function_type_arguments());
body += PushArgument();
pushed->type_args_len = num_type_params;
}
function_node_helper.SetJustRead(FunctionNodeHelper::kTypeParameters);
function_node_helper.ReadUntilExcluding(
@ -1360,8 +1349,7 @@ Fragment StreamingFlowGraphBuilder::TypeArgumentsHandling(
BuildDefaultTypeHandling(dart_function, type_parameters_offset);
if (dart_function.IsClosureFunction() &&
dart_function.NumParentTypeParameters() > 0 &&
FLAG_reify_generic_functions) {
dart_function.NumParentTypeParameters() > 0) {
LocalVariable* closure =
parsed_function()->node_sequence()->scope()->VariableAt(0);
@ -2749,15 +2737,6 @@ Fragment StreamingFlowGraphBuilder::CheckBoolean(TokenPosition 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(
LocalVariable* variable,
const AbstractType& type) {
@ -2773,23 +2752,6 @@ Fragment StreamingFlowGraphBuilder::CheckTypeArgumentBound(
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(
intptr_t kernel_offset,
const LocalScope** scope /* = nullptr */) {
@ -2973,7 +2935,6 @@ Fragment StreamingFlowGraphBuilder::BuildVariableSet(TokenPosition* p) {
if (NeedsDebugStepCheck(stack(), position)) {
instructions = DebugStepCheck(position) + instructions;
}
instructions += CheckVariableTypeInCheckedMode(variable_kernel_position);
instructions +=
StoreLocal(position, LookupVariable(variable_kernel_position));
return instructions;
@ -2990,7 +2951,6 @@ Fragment StreamingFlowGraphBuilder::BuildVariableSet(uint8_t payload,
if (NeedsDebugStepCheck(stack(), position)) {
instructions = DebugStepCheck(position) + instructions;
}
instructions += CheckVariableTypeInCheckedMode(variable_kernel_position);
instructions +=
StoreLocal(position, LookupVariable(variable_kernel_position));
@ -3023,7 +2983,7 @@ Fragment StreamingFlowGraphBuilder::BuildPropertyGet(TokenPosition* p) {
const Function* interface_target = &Function::null_function();
const NameIndex itarget_name =
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))) {
interface_target = &Function::ZoneHandle(
Z,
@ -3103,7 +3063,7 @@ Fragment StreamingFlowGraphBuilder::BuildPropertySet(TokenPosition* p) {
const Function* interface_target = &Function::null_function();
const NameIndex itarget_name =
ReadCanonicalNameReference(); // read interface_target_reference.
if (FLAG_strong && !H.IsRoot(itarget_name)) {
if (!H.IsRoot(itarget_name)) {
interface_target = &Function::ZoneHandle(
Z,
H.LookupMethodByMember(itarget_name, H.DartSetterName(itarget_name)));
@ -3515,13 +3475,10 @@ Fragment StreamingFlowGraphBuilder::BuildStaticSet(TokenPosition* p) {
if (H.IsField(target)) {
const Field& field =
Field::ZoneHandle(Z, H.LookupFieldByKernelField(target));
const AbstractType& dst_type = AbstractType::ZoneHandle(Z, field.type());
Fragment instructions = BuildExpression(); // read expression.
if (NeedsDebugStepCheck(stack(), position)) {
instructions = DebugStepCheck(position) + instructions;
}
instructions += CheckAssignableInCheckedMode(
dst_type, String::ZoneHandle(Z, field.name()));
LocalVariable* variable = MakeTemporary();
instructions += LoadLocal(variable);
return instructions + StoreStaticField(position, field);
@ -3619,7 +3576,7 @@ Fragment StreamingFlowGraphBuilder::BuildMethodInvocation(TokenPosition* p) {
intptr_t type_args_len = 0;
LocalVariable* type_arguments_temp = NULL;
if (FLAG_reify_generic_functions) {
{
AlternativeReadingScope alt(&reader_);
SkipExpression(); // skip receiver
SkipName(); // skip method name
@ -3707,7 +3664,7 @@ Fragment StreamingFlowGraphBuilder::BuildMethodInvocation(TokenPosition* p) {
const Function* interface_target = &Function::null_function();
const NameIndex itarget_name =
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(
Z, H.LookupMethodByMember(itarget_name,
H.DartProcedureName(itarget_name)));
@ -3807,7 +3764,7 @@ Fragment StreamingFlowGraphBuilder::BuildDirectMethodInvocation(
Fragment instructions;
intptr_t type_args_len = 0;
if (FLAG_reify_generic_functions) {
{
AlternativeReadingScope alt(&reader_);
SkipExpression(); // skip receiver
ReadCanonicalNameReference(); // skip target reference
@ -3873,7 +3830,7 @@ Fragment StreamingFlowGraphBuilder::BuildSuperMethodInvocation(
inferred_type_metadata_helper_.GetInferredType(offset);
intptr_t type_args_len = 0;
if (FLAG_reify_generic_functions) {
{
AlternativeReadingScope alt(&reader_);
SkipName(); // skip method name
ReadUInt(); // read argument count.
@ -3977,7 +3934,7 @@ Fragment StreamingFlowGraphBuilder::BuildSuperMethodInvocation(
} else {
Fragment instructions;
if (FLAG_reify_generic_functions) {
{
AlternativeReadingScope alt(&reader_);
ReadUInt(); // read argument count.
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);
instructions += TranslateInstantiatedTypeArguments(type_arguments);
instructions += PushArgument();
} else if (!special_case && FLAG_reify_generic_functions) {
} else if (!special_case) {
AlternativeReadingScope alt(&reader_);
ReadUInt(); // read argument count.
intptr_t list_length = ReadListLength(); // read types list length.
@ -4150,31 +4107,6 @@ Fragment StreamingFlowGraphBuilder::BuildConstructorInvocation(
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.IsGeneric()) {
Type& type = Type::ZoneHandle(Z, T.ReceiverType(klass).raw());
@ -4291,10 +4223,6 @@ Fragment StreamingFlowGraphBuilder::TranslateLogicalExpressionForValue(
const bool is_bool = top->IsStrictCompare() || top->IsBooleanNegate();
if (!is_bool) {
right_value += CheckBoolean(position);
if (!FLAG_strong) {
right_value += Constant(Bool::True());
right_value += StrictCompare(Token::kEQ_STRICT);
}
}
if (negated) {
right_value += BooleanNegate();
@ -4607,23 +4535,12 @@ Fragment StreamingFlowGraphBuilder::BuildListLiteral(bool is_const,
instructions += LoadLocal(type);
instructions += IntConstant(length);
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();
for (intptr_t i = 0; i < length; ++i) {
instructions += LoadLocal(array);
instructions += IntConstant(i);
instructions += BuildExpression(); // read ith expression.
instructions += CheckAssignableInCheckedMode(
list_type, Symbols::ListLiteralElement());
instructions += StoreIndexed(kArrayCid);
instructions += Drop();
}
@ -5840,9 +5757,8 @@ Fragment StreamingFlowGraphBuilder::BuildVariableDeclaration() {
VariableDeclarationHelper helper(this);
helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
String& name = H.DartSymbolObfuscate(helper.name_index_);
AbstractType& type = T.BuildType(); // read type.
Tag tag = ReadTag(); // read (first part of) initializer.
T.BuildType(); // read type.
Tag tag = ReadTag(); // read (first part of) initializer.
Fragment instructions;
if (tag == kNothing) {
@ -5858,7 +5774,6 @@ Fragment StreamingFlowGraphBuilder::BuildVariableDeclaration() {
} else {
// 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 BuildImplicitClosureCreation(const Function& target);
Fragment CheckBoolean(TokenPosition position);
Fragment CheckAssignableInCheckedMode(const AbstractType& dst_type,
const String& dst_name);
Fragment CheckArgumentType(LocalVariable* variable, const AbstractType& type);
Fragment CheckTypeArgumentBound(const AbstractType& parameter,
const AbstractType& bound,
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,
const LocalScope** scope = nullptr);
Fragment ExitScope(intptr_t kernel_offset);

View file

@ -297,14 +297,14 @@ void KernelFingerprintHelper::CalculateFunctionTypeFingerprint(bool simple) {
void KernelFingerprintHelper::CalculateGetterNameFingerprint() {
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());
}
}
void KernelFingerprintHelper::CalculateSetterNameFingerprint() {
const NameIndex name = ReadCanonicalNameReference();
if (FLAG_strong && !H.IsRoot(name)) {
if (!H.IsRoot(name)) {
BuildHash(H.DartSetterName(name).Hash());
}
}
@ -312,7 +312,7 @@ void KernelFingerprintHelper::CalculateSetterNameFingerprint() {
void KernelFingerprintHelper::CalculateMethodNameFingerprint() {
const NameIndex name =
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());
}
}

View file

@ -154,10 +154,6 @@ Fragment FlowGraphBuilder::LoadInstantiatorTypeArguments() {
// arguments of the current function.
Fragment FlowGraphBuilder::LoadFunctionTypeArguments() {
Fragment instructions;
if (!FLAG_reify_generic_functions) {
instructions += NullConstant();
return instructions;
}
const Function& function = parsed_function_->function();
@ -442,8 +438,7 @@ Fragment FlowGraphBuilder::NativeCall(const String* name,
const Function* function) {
InlineBailout("kernel::FlowGraphBuilder::NativeCall");
const intptr_t num_args =
function->NumParameters() +
((function->IsGeneric() && FLAG_reify_generic_functions) ? 1 : 0);
function->NumParameters() + (function->IsGeneric() ? 1 : 0);
ArgumentArray arguments = GetArguments(num_args);
NativeCallInstr* call =
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
// and in strong mode for native functions.
if (!omit_result_type_check &&
(I->type_checks() || (function.is_native() && FLAG_strong))) {
if (!omit_result_type_check && function.is_native()) {
const AbstractType& return_type =
AbstractType::Handle(Z, function.result_type());
instructions += CheckAssignable(return_type, Symbols::FunctionResult());
@ -587,23 +581,6 @@ Fragment FlowGraphBuilder::StaticCall(TokenPosition position,
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) {
Value* array = Pop();
StringInterpolateInstr* interpolate =
@ -921,7 +898,7 @@ Fragment FlowGraphBuilder::NativeFunctionBody(const Function& function,
break;
default: {
String& name = String::ZoneHandle(Z, function.native_name());
if (function.IsGeneric() && FLAG_reify_generic_functions) {
if (function.IsGeneric()) {
body += LoadLocal(parsed_function_->RawTypeArgumentsVariable());
body += PushArgument();
}
@ -1032,9 +1009,6 @@ Fragment FlowGraphBuilder::BuildImplicitClosureCreation(
Fragment FlowGraphBuilder::CheckVariableTypeInCheckedMode(
const AbstractType& dst_type,
const String& name_symbol) {
if (I->type_checks()) {
return CheckAssignable(dst_type, name_symbol);
}
return Fragment();
}
@ -1078,12 +1052,10 @@ Fragment FlowGraphBuilder::EvaluateAssertion() {
Fragment FlowGraphBuilder::CheckBoolean(TokenPosition position) {
Fragment instructions;
if (FLAG_strong || I->type_checks() || I->asserts()) {
LocalVariable* top_of_stack = MakeTemporary();
instructions += LoadLocal(top_of_stack);
instructions += AssertBool(position);
instructions += Drop();
}
LocalVariable* top_of_stack = MakeTemporary();
instructions += LoadLocal(top_of_stack);
instructions += AssertBool(position);
instructions += Drop();
return instructions;
}

View file

@ -137,8 +137,6 @@ class FlowGraphBuilder : public BaseFlowGraphBuilder {
const InferredTypeMetadata* result_type = NULL,
intptr_t type_args_len = 0,
bool use_unchecked_entry = false);
Fragment StoreInstanceFieldGuarded(const Field& field,
bool is_initialization_store);
Fragment StringInterpolate(TokenPosition position);
Fragment StringInterpolateSingle(TokenPosition position);
Fragment ThrowTypeError();

View file

@ -2944,16 +2944,12 @@ void TypeTranslator::BuildTypeParameterType() {
: 0;
if (procedure_type_parameter_count > 0) {
if (procedure_type_parameter_count > parameter_index) {
if (FLAG_reify_generic_functions) {
result_ ^=
TypeArguments::Handle(Z, active_class_->member->type_parameters())
.TypeAt(parameter_index);
if (finalize_) {
result_ =
ClassFinalizer::FinalizeType(*active_class_->klass, result_);
}
} else {
result_ ^= Type::DynamicType();
result_ ^=
TypeArguments::Handle(Z, active_class_->member->type_parameters())
.TypeAt(parameter_index);
if (finalize_) {
result_ =
ClassFinalizer::FinalizeType(*active_class_->klass, result_);
}
return;
}
@ -2963,12 +2959,7 @@ void TypeTranslator::BuildTypeParameterType() {
if (active_class_->local_type_parameters != NULL) {
if (parameter_index < active_class_->local_type_parameters->Length()) {
if (FLAG_reify_generic_functions) {
result_ ^=
active_class_->local_type_parameters->TypeAt(parameter_index);
} else {
result_ ^= Type::DynamicType();
}
result_ ^= active_class_->local_type_parameters->TypeAt(parameter_index);
if (finalize_) {
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 bool load_optional_arguments = function_.HasOptionalParameters();
const bool expect_type_args =
function_.IsGeneric() && FLAG_reify_generic_functions;
const bool expect_type_args = function_.IsGeneric();
const bool check_arguments = function_.IsClosureFunction();
Fragment prologue = Fragment(entry);

View file

@ -113,8 +113,7 @@ ScopeBuildingResult* ScopeBuilder::BuildScopes() {
scope_->set_end_token_pos(function.end_token_pos());
// Add function type arguments variable before current context variable.
if (FLAG_reify_generic_functions &&
(function.IsGeneric() || function.HasGenericParent())) {
if ((function.IsGeneric() || function.HasGenericParent())) {
LocalVariable* type_args_var = MakeVariable(
TokenPosition::kNoSource, TokenPosition::kNoSource,
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) \
case k##ename: { \
const intptr_t cid = k##result_type##Cid; \
if (FLAG_strong && cid != kDynamicCid) { \
if (cid != kDynamicCid) { \
String& err = String::Handle(); \
err = function.QualifiedScrubbedName(); \
err = String::Concat( \

View file

@ -326,7 +326,7 @@ char* Dart::Init(const uint8_t* vm_isolate_snapshot,
}
const bool is_dart2_aot_precompiler =
FLAG_strong && FLAG_precompiled_mode && !kDartPrecompiledRuntime;
FLAG_precompiled_mode && !kDartPrecompiledRuntime;
if (!is_dart2_aot_precompiler &&
(FLAG_support_service || !kDartPrecompiledRuntime)) {
@ -717,25 +717,11 @@ const char* Dart::FeaturesString(Isolate* isolate,
buffer.AddString(name ? (" " #name) : (" no-" #name)); \
} 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)) {
// Checked mode affects deopt ids.
ADD_FLAG(type_checks, enable_type_checks, FLAG_enable_type_checks);
// enabling assertions affects deopt ids.
ADD_FLAG(asserts, enable_asserts, FLAG_enable_asserts);
ADD_FLAG(error_on_bad_type, enable_error_on_bad_type,
FLAG_error_on_bad_type);
// sync-async and reify_generic_functions also affect deopt_ids.
// sync-async affects deopt_ids.
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) {
ADD_FLAG(use_field_guards, use_field_guards, FLAG_use_field_guards);
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.
Dart_IsolateFlags api_flags;
Isolate::FlagsInitialize(&api_flags);
api_flags.enable_type_checks = true;
api_flags.enable_asserts = true;
api_flags.enable_error_on_bad_type = true;
char* err;
Dart_Isolate isolate =
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
// any dart code in the Dart 2.0 AOT compiler.
#if !defined(DART_PRECOMPILED_RUNTIME)
if (FLAG_strong && FLAG_precompiled_mode) {
if (FLAG_precompiled_mode) {
UNREACHABLE();
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)

View file

@ -92,11 +92,6 @@ constexpr bool kDartPrecompiledRuntime = false;
"Compile expressions with the Kernel front-end.") \
P(enable_mirrors, bool, true, \
"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, \
"Don't optimize away static field initialization") \
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_native_memory, false, bool, false, \
"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") \
C(stress_async_stacks, false, false, bool, false, \
"Stress test async stack traces") \
P(strong, bool, true, "Enable strong mode.") \
P(sync_async, bool, true, "Start `async` functions synchronously.") \
R(support_disassembler, false, bool, true, "Support the disassembler.") \
R(support_il_printer, false, bool, true, "Support the IL printer.") \

View file

@ -194,8 +194,7 @@ class InterpreterHelpers {
static bool ObjectArraySetIndexed(Thread* thread,
RawObject** FP,
RawObject** result) {
return !thread->isolate()->type_checks() &&
ObjectArraySetIndexedUnchecked(thread, FP, result);
return ObjectArraySetIndexedUnchecked(thread, FP, result);
}
static bool ObjectArraySetIndexedUnchecked(Thread* thread,
@ -228,8 +227,7 @@ class InterpreterHelpers {
static bool GrowableArraySetIndexed(Thread* thread,
RawObject** FP,
RawObject** result) {
return !thread->isolate()->type_checks() &&
GrowableArraySetIndexedUnchecked(thread, FP, result);
return GrowableArraySetIndexedUnchecked(thread, FP, result);
}
static bool GrowableArraySetIndexedUnchecked(Thread* thread,

View file

@ -68,7 +68,6 @@ DECLARE_FLAG(bool, trace_reload);
#if !defined(PRODUCT)
static void CheckedModeHandler(bool value) {
FLAG_enable_asserts = value;
FLAG_enable_type_checks = value;
}
// --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)
//
#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, error_on_bad_type, ErrorOnBadType, enable_error_on_bad_type, \
FLAG_error_on_bad_type) \
V(NONPRODUCT, use_field_guards, UseFieldGuards, use_field_guards, \
FLAG_use_field_guards) \
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 {
return FLAG_strong && FLAG_use_strong_mode_types &&
!unsafe_trust_strong_mode_types();
return FLAG_use_strong_mode_types && !unsafe_trust_strong_mode_types();
}
bool should_load_vmservice() const {
@ -746,12 +741,10 @@ class Isolate : public BaseIsolate {
// Convenience flag tester indicating whether incoming function arguments
// should be type checked.
bool argument_type_checks() const {
return should_emit_strong_mode_checks() || type_checks();
}
bool argument_type_checks() const { return should_emit_strong_mode_checks(); }
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);

View file

@ -593,8 +593,6 @@ RawObject* BuildParameterDescriptor(const Function& function) {
}
bool NeedsDynamicInvocationForwarder(const Function& function) {
ASSERT(FLAG_strong);
Thread* thread = Thread::Current();
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).
Dart_IsolateFlags api_flags;
Isolate::FlagsInitialize(&api_flags);
api_flags.enable_type_checks = false;
api_flags.enable_asserts = false;
api_flags.enable_error_on_bad_type = false;
api_flags.unsafe_trust_strong_mode_types = false;
#if !defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC)
api_flags.use_field_guards = true;
@ -547,7 +545,7 @@ class KernelCompilationRequest : public ValueObject {
Dart_CObject dart_strong;
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
// compilation logic out of CreateIsolateAndSetupHelper and into

View file

@ -84,19 +84,7 @@ TEST_CASE(Mixin_PrivateSuperResolutionCrossLibraryShouldFail) {
Dart_Handle lib = TestCase::LoadTestScriptWithDFE(
sizeof(sourcefiles) / sizeof(Dart_SourceFile), sourcefiles,
/* resolver= */ NULL, /* finalize= */ true, /* incrementally= */ true);
if (FLAG_strong) {
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);
}
EXPECT_ERROR(lib, "Error: Superclass has no method named '_bar'.");
}
#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)

View file

@ -180,7 +180,7 @@ class NativeArguments {
if (function.IsClosureFunction()) {
function_bits |= kClosureFunctionBit;
}
if (function.IsGeneric() && FLAG_reify_generic_functions) {
if (function.IsGeneric()) {
function_bits |= kGenericFunctionBit;
argc++;
}

View file

@ -4310,27 +4310,21 @@ bool Class::TypeTestNonRecursive(const Class& cls,
other.IsVoidClass()) {
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.
if (this_class.IsNullClass()) {
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'.
// If so, apply additional subtyping rules.
if (FLAG_strong && this_class.FutureOrTypeTest(
zone, type_arguments, other, other_type_arguments,
bound_error, bound_trail, space)) {
if (this_class.FutureOrTypeTest(zone, type_arguments, other,
other_type_arguments, bound_error,
bound_trail, space)) {
return true;
}
// In the case of a subtype test, each occurrence of DynamicType in type S
// 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.
// DynamicType is not more specific than any type.
if (this_class.IsDynamicClass()) {
return !FLAG_strong && (test_kind == Class::kIsSubtypeOf);
return false;
}
// If other is neither Object, dynamic or void, then ObjectType/VoidType
// 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
// it would have to have all dynamic type arguments which is checked
// above.
return !FLAG_strong && (test_kind == Class::kIsSubtypeOf);
return false;
}
return type_arguments.TypeTest(test_kind, other_type_arguments,
from_index, num_type_params, bound_error,
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
// and check for transitivity at the same time.
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.
if (FLAG_strong && interface_class.IsDartFunctionClass()) {
if (interface_class.IsDartFunctionClass()) {
continue;
}
if (interface_class.TypeTest(test_kind, interface_args, other,
@ -4470,7 +4455,6 @@ bool Class::FutureOrTypeTest(Zone* zone,
Heap::Space space) const {
// In strong mode, there is no difference between 'is subtype of' and
// 'is more specific than'.
ASSERT(FLAG_strong);
if (other.IsFutureOrClass()) {
if (other_type_arguments.IsNull()) {
return true;
@ -4553,31 +4537,6 @@ RawFunction* Class::LookupFunctionAllowPrivate(const String& name) const {
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'.
static bool MatchesAccessorName(const String& name,
const char* prefix,
@ -5149,7 +5108,6 @@ RawString* TypeArguments::SubvectorName(intptr_t from_index,
name = type.BuildName(name_visibility);
} else {
// Show dynamic type argument in strong mode.
ASSERT(FLAG_strong);
name = Symbols::Dynamic().raw();
}
pieces.Add(name);
@ -7248,36 +7206,15 @@ bool Function::TestParameterType(TypeTestKind test_kind,
Error* bound_error,
TrailPtr bound_trail,
Heap::Space space) const {
if (FLAG_strong) {
const AbstractType& param_type =
AbstractType::Handle(ParameterTypeAt(parameter_position));
if (param_type.IsTopType()) {
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& param_type =
AbstractType::Handle(ParameterTypeAt(parameter_position));
if (param_type.IsTopType()) {
return true;
}
const AbstractType& other_param_type =
AbstractType::Handle(other.ParameterTypeAt(other_parameter_position));
if (other_param_type.IsDynamicType()) {
return true;
}
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);
return other_param_type.IsSubtypeOf(param_type, bound_error, bound_trail,
space);
}
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)) {
return false;
}
if (FLAG_reify_generic_functions) {
// Check the type parameters and bounds of generic functions.
if (!HasSameTypeParametersAndBounds(other)) {
return false;
}
// Check the type parameters and bounds of generic functions.
if (!HasSameTypeParametersAndBounds(other)) {
return false;
}
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
// Check the result type.
const AbstractType& other_res_type =
AbstractType::Handle(zone, other.result_type());
if (FLAG_strong) {
// In strong mode, 'void Function()' is a subtype of 'Object Function()'.
if (!other_res_type.IsTopType()) {
const AbstractType& res_type = AbstractType::Handle(zone, result_type());
if (!res_type.IsSubtypeOf(other_res_type, bound_error, bound_trail,
space)) {
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;
}
}
// In strong mode, 'void Function()' is a subtype of 'Object Function()'.
if (!other_res_type.IsTopType()) {
const AbstractType& res_type = AbstractType::Handle(zone, result_type());
if (!res_type.IsSubtypeOf(other_res_type, bound_error, bound_trail,
space)) {
return false;
}
}
// 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
// closure of a method compiled by kernel.
// 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());
kernel::TranslationHelper translation_helper(thread);
translation_helper.InitFromScript(function_script);
@ -7886,31 +7796,29 @@ RawString* Function::BuildSignature(NameVisibility name_visibility) const {
Zone* zone = thread->zone();
GrowableHandlePtrArray<const String> pieces(zone, 4);
String& name = String::Handle(zone);
if (FLAG_reify_generic_functions) {
const TypeArguments& type_params =
TypeArguments::Handle(zone, type_parameters());
if (!type_params.IsNull()) {
const intptr_t num_type_params = type_params.Length();
ASSERT(num_type_params > 0);
TypeParameter& type_param = TypeParameter::Handle(zone);
AbstractType& bound = AbstractType::Handle(zone);
pieces.Add(Symbols::LAngleBracket());
for (intptr_t i = 0; i < num_type_params; i++) {
type_param ^= type_params.TypeAt(i);
name = type_param.name();
const TypeArguments& type_params =
TypeArguments::Handle(zone, type_parameters());
if (!type_params.IsNull()) {
const intptr_t num_type_params = type_params.Length();
ASSERT(num_type_params > 0);
TypeParameter& type_param = TypeParameter::Handle(zone);
AbstractType& bound = AbstractType::Handle(zone);
pieces.Add(Symbols::LAngleBracket());
for (intptr_t i = 0; i < num_type_params; i++) {
type_param ^= type_params.TypeAt(i);
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);
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());
BuildSignatureParameters(thread, zone, name_visibility, &pieces);
@ -16424,8 +16332,7 @@ bool Instance::IsInstanceOf(
other_instantiator_type_arguments, other_function_type_arguments,
kAllFree, bound_error, NULL, NULL, Heap::kOld);
if ((bound_error != NULL) && !bound_error->IsNull()) {
ASSERT(Isolate::Current()->type_checks());
return false;
UNREACHABLE();
}
if (instantiated_other.IsTypeRef()) {
instantiated_other = TypeRef::Cast(instantiated_other).type();
@ -16435,8 +16342,7 @@ bool Instance::IsInstanceOf(
return true;
}
}
if (FLAG_strong &&
IsFutureOrInstanceOf(zone, instantiated_other, bound_error)) {
if (IsFutureOrInstanceOf(zone, instantiated_other, bound_error)) {
return true;
}
if (!instantiated_other.IsFunctionType()) {
@ -16472,7 +16378,7 @@ bool Instance::IsInstanceOf(
other_instantiator_type_arguments, other_function_type_arguments,
kAllFree, bound_error, NULL, NULL, Heap::kOld);
if ((bound_error != NULL) && !bound_error->IsNull()) {
ASSERT(Isolate::Current()->type_checks());
UNREACHABLE();
return false;
}
if (instantiated_other.IsTypeRef()) {
@ -16483,46 +16389,15 @@ bool Instance::IsInstanceOf(
}
}
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()) {
return false;
}
other_class = instantiated_other.type_class();
if (IsNull()) {
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.
if (FLAG_strong &&
IsFutureOrInstanceOf(zone, instantiated_other, bound_error)) {
if (IsFutureOrInstanceOf(zone, instantiated_other, bound_error)) {
return true;
}
return other_class.IsNullClass() || other_class.IsObjectClass();
@ -16534,7 +16409,6 @@ bool Instance::IsInstanceOf(
bool Instance::IsFutureOrInstanceOf(Zone* zone,
const AbstractType& other,
Error* bound_error) const {
ASSERT(FLAG_strong);
if (other.IsType() &&
Class::Handle(zone, other.type_class()).IsFutureOrClass()) {
if (other.arguments() == TypeArguments::null()) {
@ -17091,10 +16965,6 @@ RawString* AbstractType::BuildName(NameVisibility name_visibility) const {
num_type_params = num_args;
} else {
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 {
// 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);
pieces.Add(class_name);
if ((num_type_params == 0) ||
(!FLAG_strong && args.IsRaw(first_type_param_index, num_type_params))) {
if (num_type_params == 0) {
// Do nothing.
} else {
const String& args_name = String::Handle(
@ -17159,20 +17028,18 @@ bool AbstractType::IsTopType() const {
return true;
}
// In strong mode, FutureOr<T> where T is a top type behaves as a top type.
if (FLAG_strong) {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
if (Class::Handle(zone, type_class()).IsFutureOrClass()) {
if (arguments() == TypeArguments::null()) {
return true;
}
const TypeArguments& type_arguments =
TypeArguments::Handle(zone, arguments());
const AbstractType& type_arg =
AbstractType::Handle(zone, type_arguments.TypeAt(0));
if (type_arg.IsTopType()) {
return true;
}
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
if (Class::Handle(zone, type_class()).IsFutureOrClass()) {
if (arguments() == TypeArguments::null()) {
return true;
}
const TypeArguments& type_arguments =
TypeArguments::Handle(zone, arguments());
const AbstractType& type_arg =
AbstractType::Handle(zone, type_arguments.TypeAt(0));
if (type_arg.IsTopType()) {
return true;
}
}
return false;
@ -17257,24 +17124,22 @@ bool AbstractType::TypeTest(TypeTestKind test_kind,
// However, in checked mode, a function type may include malbounded result
// type and/or malbounded parameter types, which will then be encountered here
// 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()) {
ASSERT(Isolate::Current()->type_checks());
if ((bound_error != NULL) && bound_error->IsNull()) {
*bound_error = error();
UNREACHABLE();
}
return false;
}
if (other.IsMalbounded()) {
ASSERT(Isolate::Current()->type_checks());
if ((bound_error != NULL) && bound_error->IsNull()) {
*bound_error = other.error();
UNREACHABLE();
}
return false;
}
// 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
// comparing function-types).
// As of Dart 1.5, the Null type is a subtype of (and is more specific than)
// As of Dart 2.0, the Null type is a subtype of (and is more specific than)
// any type.
if (other.IsTopType() || IsNullType()) {
return true;
@ -17360,8 +17225,7 @@ bool AbstractType::TypeTest(TypeTestKind test_kind,
}
// In strong mode, check if 'other' is 'FutureOr'.
// If so, apply additional subtyping rules.
if (FLAG_strong &&
FutureOrTypeTest(zone, other, bound_error, bound_trail, space)) {
if (FutureOrTypeTest(zone, other, bound_error, bound_trail, space)) {
return true;
}
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,
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()) {
// [this] is not a function type (and, in non-strong mode, does not
// declare a compatible call() method as verified above). Therefore,
@ -17425,8 +17267,7 @@ bool AbstractType::TypeTest(TypeTestKind test_kind,
if (IsFunctionType()) {
// In strong mode, check if 'other' is 'FutureOr'.
// If so, apply additional subtyping rules.
if (FLAG_strong &&
FutureOrTypeTest(zone, other, bound_error, bound_trail, space)) {
if (FutureOrTypeTest(zone, other, bound_error, bound_trail, space)) {
return true;
}
return false;
@ -17444,7 +17285,6 @@ bool AbstractType::FutureOrTypeTest(Zone* zone,
Heap::Space space) const {
// In strong mode, there is no difference between 'is subtype of' and
// 'is more specific than'.
ASSERT(FLAG_strong);
if (other.IsType() &&
Class::Handle(zone, other.type_class()).IsFutureOrClass()) {
if (other.arguments() == TypeArguments::null()) {
@ -17611,18 +17451,7 @@ bool Type::IsMalformed() const {
}
bool Type::IsMalbounded() const {
if (raw_ptr()->sig_or_err_.error_ == LanguageError::null()) {
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;
return false;
}
bool Type::IsMalformedOrMalbounded() const {
@ -17637,7 +17466,7 @@ bool Type::IsMalformedOrMalbounded() const {
return true;
}
ASSERT(type_error.kind() == Report::kMalboundedType);
return Isolate::Current()->type_checks();
return false;
}
RawLanguageError* Type::error() const {
@ -17895,12 +17724,10 @@ bool Type::IsEquivalent(const Instance& other, TrailPtr trail) const {
const Function& other_sig_fun =
Function::Handle(zone, other_type.signature());
if (FLAG_reify_generic_functions) {
// Compare function type parameters and their bounds.
// Check the type parameters and bounds of generic functions.
if (!sig_fun.HasSameTypeParametersAndBounds(other_sig_fun)) {
return false;
}
// Compare function type parameters and their bounds.
// Check the type parameters and bounds of generic functions.
if (!sig_fun.HasSameTypeParametersAndBounds(other_sig_fun)) {
return false;
}
// Compare number of function parameters.
@ -19035,58 +18862,6 @@ RawAbstractType* BoundedType::InstantiateFrom(
// (or instantiated) either.
// 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();
}

View file

@ -1087,7 +1087,6 @@ class Class : public Object {
RawFunction* LookupFunctionAllowPrivate(const String& name) const;
RawFunction* LookupGetterFunction(const String& name) const;
RawFunction* LookupSetterFunction(const String& name) const;
RawFunction* LookupCallFunctionForTypeTest() const;
RawField* LookupInstanceField(const String& name) const;
RawField* LookupStaticField(const String& name) const;
RawField* LookupField(const String& name) const;
@ -2493,14 +2492,11 @@ class Function : public Object {
bool IsInFactoryScope() const;
bool NeedsArgumentTypeChecks(Isolate* I) const {
if (FLAG_strong) {
if (!I->should_emit_strong_mode_checks()) {
return false;
}
return IsClosureFunction() ||
!(is_static() || (kind() == RawFunction::kConstructor));
if (!I->should_emit_strong_mode_checks()) {
return false;
}
return I->type_checks();
return IsClosureFunction() ||
!(is_static() || (kind() == RawFunction::kConstructor));
}
bool MayHaveUncheckedEntryPoint(Isolate* I) const;

View file

@ -74,8 +74,7 @@ ParsedFunction::ParsedFunction(Thread* thread, const Function& function)
Symbols::CurrentContextVar(), Object::dynamic_type());
current_context_var_ = temp;
const bool reify_generic_argument =
function.IsGeneric() && FLAG_reify_generic_functions;
const bool reify_generic_argument = function.IsGeneric();
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
// instantiator can be reused as type argument vector.
ASSERT(!type_arguments.IsUninstantiatedIdentity());
if (isolate->type_checks()) {
Error& bound_error = Error::Handle(zone);
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);
}
type_arguments = type_arguments.InstantiateAndCanonicalizeFrom(
instantiator_type_arguments, function_type_arguments, NULL);
ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated());
arguments.SetReturn(type_arguments);
}
@ -833,8 +817,7 @@ DEFINE_RUNTIME_ENTRY(TypeCheck, 7) {
}
String& bound_error_message = String::Handle(zone);
if (!bound_error.IsNull()) {
ASSERT(isolate->type_checks());
bound_error_message = String::New(bound_error.ToErrorCString());
UNREACHABLE();
}
if (dst_name.IsNull()) {
#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32)

View file

@ -191,8 +191,7 @@ class SimulatorHelpers {
static bool ObjectArraySetIndexed(Thread* thread,
RawObject** FP,
RawObject** result) {
return !thread->isolate()->type_checks() &&
ObjectArraySetIndexedUnchecked(thread, FP, result);
return ObjectArraySetIndexedUnchecked(thread, FP, result);
}
static bool ObjectArraySetIndexedUnchecked(Thread* thread,
@ -225,8 +224,7 @@ class SimulatorHelpers {
static bool GrowableArraySetIndexed(Thread* thread,
RawObject** FP,
RawObject** result) {
return !thread->isolate()->type_checks() &&
GrowableArraySetIndexedUnchecked(thread, FP, result);
return GrowableArraySetIndexedUnchecked(thread, FP, result);
}
static bool GrowableArraySetIndexedUnchecked(Thread* thread,

View file

@ -4,9 +4,6 @@
# Sections in this file should contain "$runtime == flutter".
# 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:
# 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 ]
async_await_syntax_test/a05c: CompileTimeError