mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 22:59:47 +00:00
[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>
This commit is contained in:
parent
8422bf1a80
commit
1a4cff1bd4
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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_);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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( \
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.") \
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
|
|
@ -4313,27 +4313,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.
|
||||
|
@ -4360,21 +4354,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());
|
||||
|
@ -4427,7 +4412,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,
|
||||
|
@ -4473,7 +4458,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;
|
||||
|
@ -4556,31 +4540,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,
|
||||
|
@ -5152,7 +5111,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);
|
||||
|
@ -7251,36 +7209,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 {
|
||||
|
@ -7342,48 +7279,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.
|
||||
|
@ -7725,7 +7635,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);
|
||||
|
@ -7889,31 +7799,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);
|
||||
|
@ -16427,8 +16335,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();
|
||||
|
@ -16438,8 +16345,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()) {
|
||||
|
@ -16475,7 +16381,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()) {
|
||||
|
@ -16486,46 +16392,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();
|
||||
|
@ -16537,7 +16412,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()) {
|
||||
|
@ -17094,10 +16968,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
|
||||
|
@ -17110,8 +16980,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(
|
||||
|
@ -17162,20 +17031,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;
|
||||
|
@ -17260,24 +17127,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;
|
||||
|
@ -17363,8 +17228,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".
|
||||
|
@ -17389,28 +17253,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,
|
||||
|
@ -17428,8 +17270,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;
|
||||
|
@ -17447,7 +17288,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()) {
|
||||
|
@ -17614,18 +17454,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 {
|
||||
|
@ -17640,7 +17469,7 @@ bool Type::IsMalformedOrMalbounded() const {
|
|||
return true;
|
||||
}
|
||||
ASSERT(type_error.kind() == Report::kMalboundedType);
|
||||
return Isolate::Current()->type_checks();
|
||||
return false;
|
||||
}
|
||||
|
||||
RawLanguageError* Type::error() const {
|
||||
|
@ -17898,12 +17727,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.
|
||||
|
@ -19038,58 +18865,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();
|
||||
}
|
||||
|
||||
|
|
|
@ -1080,7 +1080,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;
|
||||
|
@ -2486,14 +2485,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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue