[VM/nnbd] Remove propagation of library mode to runtime after spec change.

On 1/27/20, the nnbd specification changed weak and strong mode instance checks
to make them behave uniformly across legacy and opted-in libraries.
Therefore, it is not necessary anymore to propagate the library mode in
generated code to the runtime.

Change-Id: I42d3ddc6e9a921899aeac21be6374c7893a6d27c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/138111
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Régis Crelier <regis@google.com>
This commit is contained in:
Régis Crelier 2020-03-03 20:30:32 +00:00 committed by commit-bot@chromium.org
parent 5cd6b309fb
commit 5701c4fd3b
55 changed files with 372 additions and 731 deletions

View file

@ -674,8 +674,3 @@ const int argumentsLimit = 1 << 8;
// Base class for exceptions thrown when certain limit of bytecode
// format is exceeded.
abstract class BytecodeLimitExceededException {}
// Constants specifying the NNBD mode of libraries.
// Must be kept in sync with enum class NNBDMode in the VM.
const int kLegacy = 0;
const int kOptedIn = 1;

View file

@ -1272,11 +1272,6 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
}
}
void _genPushNnbdMode() {
asm.emitPushInt(
staticTypeContext.isNonNullableByDefault ? kOptedIn : kLegacy);
}
Constant _getConstant(Expression expr) {
if (expr is ConstantExpression) {
return expr.constant;
@ -1688,11 +1683,10 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
asm.emitPushNull(); // Function type arguments.
}
asm.emitPushConstant(cp.addType(type));
_genPushNnbdMode();
final argDesc = objectTable.getArgDescHandle(5);
final argDesc = objectTable.getArgDescHandle(4);
final cpIndex =
cp.addInterfaceCall(InvocationKind.method, objectInstanceOf, argDesc);
asm.emitInterfaceCall(cpIndex, 5);
asm.emitInterfaceCall(cpIndex, 4);
}
void start(Member node, bool hasCode) {
@ -2449,7 +2443,6 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
final DartType bound = (forwardingTypeParameterBounds != null)
? forwardingTypeParameterBounds[typeParam]
: typeParam.bound;
// TODO(regis): Revisit and take nnbdMode into consideration.
final DartType type = new TypeParameterType(typeParam, Nullability.legacy);
_genPushInstantiatorAndFunctionTypeArguments([type, bound]);
asm.emitPushConstant(cp.addType(type));
@ -2478,7 +2471,6 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
_genPushInstantiatorAndFunctionTypeArguments([type]);
asm.emitPushConstant(
name != null ? cp.addName(name) : cp.addString(message));
// TODO(regis): Revisit and take nnbd mode into consideration.
bool isIntOk = typeEnvironment.isSubtypeOf(
typeEnvironment.coreTypes.intLegacyRawType,
type,

View file

@ -763,7 +763,7 @@ class _NeverTypeHandle extends _TypeHandle {
other is _NeverTypeHandle && this.nullability == other.nullability;
@override
// TODO(regis): Print nullability, only if nnbd experiment is enabled?
// TODO(regis): Print nullability.
String toString() => 'Never';
}
@ -803,7 +803,7 @@ class _SimpleTypeHandle extends _TypeHandle {
this.nullability == other.nullability;
@override
// TODO(regis): Print nullability, only if nnbd experiment is enabled?
// TODO(regis): Print nullability.
String toString() => '$class_';
}
@ -857,7 +857,7 @@ class _TypeParameterHandle extends _TypeHandle {
this.nullability == other.nullability;
@override
// TODO(regis): Print nullability, only if nnbd experiment is enabled?
// TODO(regis): Print nullability.
String toString() => '$parent::TypeParam/$indexInParent';
}
@ -903,7 +903,7 @@ class _GenericTypeHandle extends _TypeHandle {
this.nullability == other.nullability;
@override
// TODO(regis): Print nullability, only if nnbd experiment is enabled?
// TODO(regis): Print nullability.
String toString() => '$class_ $typeArgs';
}
@ -956,7 +956,7 @@ class _RecursiveGenericTypeHandle extends _TypeHandle {
this.nullability == other.nullability;
@override
// TODO(regis): Print nullability, only if nnbd experiment is enabled?
// TODO(regis): Print nullability.
String toString() => '(recursive #$id) $class_ $typeArgs';
}
@ -1009,7 +1009,7 @@ class NameAndType {
this.type == other.type;
@override
// TODO(regis): Print nullability, always or only if nnbd experiment is enabled?
// TODO(regis): Print nullability.
String toString() => '$type ${name.name}';
}
@ -1152,7 +1152,7 @@ class _FunctionTypeHandle extends _TypeHandle {
this.returnType == other.returnType;
@override
// TODO(regis): Print nullability, only if nnbd experiment is enabled?
// TODO(regis): Print nullability.
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('FunctionType');

View file

@ -31,8 +31,7 @@ L1:
PushNull
PushNull
PushConstant CP#6
PushInt 0
InterfaceCall CP#7, 5
InterfaceCall CP#7, 4
JumpIfFalse L2
PushConstant CP#9
DirectCall CP#4, 1
@ -54,7 +53,7 @@ ConstantPool {
[4] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
[5] = Reserved
[6] = Type #lib::C < dart:core::String, dart:core::int, dart:core::Object, dynamic >
[7] = InterfaceCall 'dart:core::Object::_instanceOf', ArgDesc num-args 5, num-type-args 0, names []
[7] = InterfaceCall 'dart:core::Object::_instanceOf', ArgDesc num-args 4, num-type-args 0, names []
[8] = Reserved
[9] = ObjectRef '12'
[10] = Type #lib::A < dart:core::int >
@ -222,8 +221,7 @@ Bytecode {
LoadTypeArgumentsField CP#0
PushNull
PushConstant CP#1
PushInt 0
InterfaceCall CP#2, 5
InterfaceCall CP#2, 4
JumpIfFalse L1
PushConstant CP#4
DirectCall CP#5, 1
@ -234,8 +232,7 @@ L1:
LoadTypeArgumentsField CP#0
PushNull
PushConstant CP#7
PushInt 0
InterfaceCall CP#2, 5
InterfaceCall CP#2, 4
JumpIfFalse L2
PushConstant CP#8
DirectCall CP#5, 1
@ -257,7 +254,7 @@ L2:
ConstantPool {
[0] = TypeArgumentsField #lib::D
[1] = Type #lib::A < #lib::D::TypeParam/0 >
[2] = InterfaceCall 'dart:core::Object::_instanceOf', ArgDesc num-args 5, num-type-args 0, names []
[2] = InterfaceCall 'dart:core::Object::_instanceOf', ArgDesc num-args 4, num-type-args 0, names []
[3] = Reserved
[4] = ObjectRef '21'
[5] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
@ -285,8 +282,7 @@ Bytecode {
PushNull
Push r0
PushConstant CP#0
PushInt 0
InterfaceCall CP#1, 5
InterfaceCall CP#1, 4
JumpIfFalse L1
PushConstant CP#3
DirectCall CP#4, 1
@ -297,8 +293,7 @@ L1:
LoadTypeArgumentsField CP#6
Push r0
PushConstant CP#7
PushInt 0
InterfaceCall CP#1, 5
InterfaceCall CP#1, 4
JumpIfFalse L2
PushConstant CP#8
DirectCall CP#4, 1
@ -316,7 +311,7 @@ L2:
}
ConstantPool {
[0] = Type #lib::A < #lib::D::foo3::TypeParam/0 >
[1] = InterfaceCall 'dart:core::Object::_instanceOf', ArgDesc num-args 5, num-type-args 0, names []
[1] = InterfaceCall 'dart:core::Object::_instanceOf', ArgDesc num-args 4, num-type-args 0, names []
[2] = Reserved
[3] = ObjectRef '31'
[4] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []

View file

@ -61,7 +61,6 @@ void FailClosurizeConstructor(const char* name, Dart_Handle result) {
}
void TestFields(Dart_Handle target) {
// TODO(regis): Fix these tests, as a function type is not nullable.
FAIL("fld0", Dart_GetField(target, Dart_NewStringFromCString("fld0")));
FAIL("fld0",
Dart_SetField(target, Dart_NewStringFromCString("fld0"), Dart_Null()));

View file

@ -278,8 +278,7 @@ DEFINE_NATIVE_ENTRY(Ffi_storePointer, 0, 3) {
auto& new_value_type =
AbstractType::Handle(zone, new_value.GetType(Heap::kNew));
if (!new_value_type.IsSubtypeOf(NNBDMode::kLegacyLib, pointer_type_arg,
Heap::kNew)) {
if (!new_value_type.IsSubtypeOf(pointer_type_arg, Heap::kNew)) {
const String& error = String::Handle(String::NewFormatted(
"New value (%s) is not a subtype of '%s'.",
String::Handle(new_value_type.UserVisibleName()).ToCString(),

View file

@ -713,8 +713,8 @@ static RawAbstractType* InstantiateType(const AbstractType& type,
instantiator_type_args = instantiator.arguments();
}
AbstractType& result = AbstractType::Handle(type.InstantiateFrom(
NNBDMode::kLegacyLib, instantiator_type_args,
Object::null_type_arguments(), kAllFree, NULL, Heap::kOld));
instantiator_type_args, Object::null_type_arguments(), kAllFree, NULL,
Heap::kOld));
ASSERT(result.IsFinalized());
return result.Canonicalize();
}
@ -1483,8 +1483,8 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 0, 5) {
// type arguments of the type reflected by the class mirror.
ASSERT(redirect_type.IsInstantiated(kFunctions));
redirect_type ^= redirect_type.InstantiateFrom(
NNBDMode::kLegacyLib, type_arguments, Object::null_type_arguments(),
kNoneFree, NULL, Heap::kOld);
type_arguments, Object::null_type_arguments(), kNoneFree, NULL,
Heap::kOld);
redirect_type ^= redirect_type.Canonicalize();
}
@ -1513,8 +1513,7 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 0, 5) {
ArgumentsDescriptor::New(kTypeArgsLen, args.Length(), arg_names));
ArgumentsDescriptor args_descriptor(args_descriptor_array);
if (!redirected_constructor.AreValidArguments(NNBDMode::kLegacyLib,
args_descriptor, NULL)) {
if (!redirected_constructor.AreValidArguments(args_descriptor, NULL)) {
external_constructor_name = redirected_constructor.name();
ThrowNoSuchMethod(AbstractType::Handle(klass.RareType()),
external_constructor_name, explicit_args, arg_names,
@ -1524,7 +1523,7 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 0, 5) {
}
const Object& type_error =
Object::Handle(redirected_constructor.DoArgumentTypesMatch(
NNBDMode::kLegacyLib, args, args_descriptor, type_arguments));
args, args_descriptor, type_arguments));
if (!type_error.IsNull()) {
Exceptions::PropagateError(Error::Cast(type_error));
UNREACHABLE();
@ -1764,7 +1763,7 @@ DEFINE_NATIVE_ENTRY(VariableMirror_type, 0, 2) {
DEFINE_NATIVE_ENTRY(TypeMirror_subtypeTest, 0, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, a, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, b, arguments->NativeArgAt(1));
return Bool::Get(a.IsSubtypeOf(NNBDMode::kLegacyLib, b, Heap::kNew)).raw();
return Bool::Get(a.IsSubtypeOf(b, Heap::kNew)).raw();
}
#endif // !DART_PRECOMPILED_RUNTIME

View file

@ -133,7 +133,7 @@ DEFINE_NATIVE_ENTRY(Object_haveSameRuntimeType, 0, 2) {
.raw();
}
DEFINE_NATIVE_ENTRY(Object_instanceOf, 0, 5) {
DEFINE_NATIVE_ENTRY(Object_instanceOf, 0, 4) {
const Instance& instance =
Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
const TypeArguments& instantiator_type_arguments =
@ -142,11 +142,9 @@ DEFINE_NATIVE_ENTRY(Object_instanceOf, 0, 5) {
TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(2));
const AbstractType& type =
AbstractType::CheckedHandle(zone, arguments->NativeArgAt(3));
const NNBDMode nnbd_mode = static_cast<NNBDMode>(
Smi::CheckedHandle(zone, arguments->NativeArgAt(4)).Value());
ASSERT(type.IsFinalized());
const bool is_instance_of = instance.IsInstanceOf(
nnbd_mode, type, instantiator_type_arguments, function_type_arguments);
type, instantiator_type_arguments, function_type_arguments);
if (FLAG_trace_type_checks) {
const char* result_str = is_instance_of ? "true" : "false";
OS::PrintErr("Native Object.instanceOf: result %s\n", result_str);
@ -169,18 +167,8 @@ DEFINE_NATIVE_ENTRY(Object_simpleInstanceOf, 0, 2) {
AbstractType::CheckedHandle(zone, arguments->NativeArgAt(1));
ASSERT(type.IsFinalized());
ASSERT(type.IsInstantiated());
// If the instance is not null, the result of _simpleInstanceOf does not
// depend on the nnbd mode, because we only check against a rare type,
// i.e. a class. However, we need to determine the correct nnbd mode when
// the instance is null.
// Since type literals are not imported, a legacy type indicates that the
// call originated in a legacy library. Note that the type test against a
// non-legacy type (even in a legacy library) such as dynamic, void, or Null
// yield the same result independently of the mode used.
NNBDMode mode =
type.IsLegacy() ? NNBDMode::kLegacyLib : NNBDMode::kOptedInLib;
const bool is_instance_of = instance.IsInstanceOf(
mode, type, Object::null_type_arguments(), Object::null_type_arguments());
type, Object::null_type_arguments(), Object::null_type_arguments());
return Bool::Get(is_instance_of).raw();
}
@ -247,8 +235,8 @@ static bool ExtractInterfaceTypeArgs(Zone* zone,
if (!cur_interface_type_args.IsNull() &&
!cur_interface_type_args.IsInstantiated()) {
cur_interface_type_args = cur_interface_type_args.InstantiateFrom(
cur_cls.nnbd_mode(), instance_type_args,
Object::null_type_arguments(), kNoneFree, NULL, Heap::kNew);
instance_type_args, Object::null_type_arguments(), kNoneFree, NULL,
Heap::kNew);
}
if (ExtractInterfaceTypeArgs(zone, cur_interface_cls,
cur_interface_type_args, interface_cls,
@ -401,10 +389,8 @@ DEFINE_NATIVE_ENTRY(Internal_boundsCheckForPartialInstantiation, 0, 2) {
ASSERT(!supertype.IsNull());
// The supertype may not be instantiated.
// TODO(regis): What is the correct nnbd mode to use here?
if (!AbstractType::InstantiateAndTestSubtype(
NNBDMode::kLegacyLib, &subtype, &supertype, instantiator_type_args,
function_type_args)) {
&subtype, &supertype, instantiator_type_args, function_type_args)) {
// Throw a dynamic type error.
TokenPosition location;
{

View file

@ -22,7 +22,7 @@ namespace dart {
V(Object_toString, 1) \
V(Object_runtimeType, 1) \
V(Object_haveSameRuntimeType, 2) \
V(Object_instanceOf, 5) \
V(Object_instanceOf, 4) \
V(Object_simpleInstanceOf, 2) \
V(Function_apply, 2) \
V(Closure_equals, 2) \

View file

@ -390,16 +390,14 @@ void ClassFinalizer::CheckRecursiveType(const Class& cls,
!pending_arguments.IsSubvectorInstantiated(first_type_param,
num_type_params)) {
const TypeArguments& instantiated_arguments = TypeArguments::Handle(
zone, arguments.InstantiateFrom(NNBDMode::kLegacyLib,
Object::null_type_arguments(),
zone, arguments.InstantiateFrom(Object::null_type_arguments(),
Object::null_type_arguments(),
kNoneFree, NULL, Heap::kNew));
const TypeArguments& instantiated_pending_arguments =
TypeArguments::Handle(
zone, pending_arguments.InstantiateFrom(
NNBDMode::kLegacyLib, Object::null_type_arguments(),
Object::null_type_arguments(), kNoneFree, NULL,
Heap::kNew));
TypeArguments::Handle(zone, pending_arguments.InstantiateFrom(
Object::null_type_arguments(),
Object::null_type_arguments(),
kNoneFree, NULL, Heap::kNew));
// By using TypeEquality::kInSubtypeTest, we throw a wider net than
// using canonical or syntactical equality and may reject more
// problematic declarations.
@ -625,8 +623,8 @@ void ClassFinalizer::FinalizeTypeArguments(const Class& cls,
continue;
}
super_type_arg = super_type_arg.InstantiateFrom(
cls.nnbd_mode(), arguments, Object::null_type_arguments(),
kNoneFree, instantiation_trail, Heap::kOld);
arguments, Object::null_type_arguments(), kNoneFree,
instantiation_trail, Heap::kOld);
if (super_type_arg.IsBeingFinalized()) {
// The super_type_arg was instantiated from a type being finalized.
// We need to finish finalizing its type arguments.
@ -783,8 +781,8 @@ RawAbstractType* ClassFinalizer::FinalizeType(const Class& cls,
const TypeArguments& instantiator_type_arguments =
TypeArguments::Handle(zone, fun_type.arguments());
signature = signature.InstantiateSignatureFrom(
scope_class.nnbd_mode(), instantiator_type_arguments,
Object::null_type_arguments(), kNoneFree, Heap::kOld);
instantiator_type_arguments, Object::null_type_arguments(),
kNoneFree, Heap::kOld);
// Note that if instantiator_type_arguments contains type parameters,
// as in F<K>, the signature is still uninstantiated (the typedef type
// parameters were substituted in the signature with typedef type

View file

@ -1310,7 +1310,7 @@ void AotCallSpecializer::TryReplaceWithDispatchTableCall(
const AbstractType& target_type =
AbstractType::Handle(Class::Handle(interface_target.Owner()).RareType());
const bool receiver_can_be_smi =
CompileType::Smi().IsAssignableTo(NNBDMode::kLegacyLib, target_type);
CompileType::Smi().IsAssignableTo(target_type);
auto load_cid = new (Z) LoadClassIdInstr(receiver->CopyWithType(Z), kUntagged,
receiver_can_be_smi);
InsertBefore(call, load_cid, call->env(), FlowGraph::kValue);

View file

@ -17,7 +17,6 @@ class Definition;
class FlowGraphSerializer;
class SExpression;
class SExpList;
enum class NNBDMode;
template <typename T>
class GrowableArray;
@ -39,7 +38,6 @@ class CompileType : public ZoneAllocated {
static const bool kNullable = true;
static const bool kNonNullable = false;
// TODO(regis): Should CompileType take an NNBDMode?
CompileType(bool is_nullable, intptr_t cid, const AbstractType* type)
: is_nullable_(is_nullable), cid_(cid), type_(type) {}
@ -57,7 +55,6 @@ class CompileType : public ZoneAllocated {
return *this;
}
// TODO(regis): Should we also consider type_.nullability() here?
bool is_nullable() const { return is_nullable_; }
// Return type such that concrete value's type in runtime is guaranteed to
@ -80,11 +77,11 @@ class CompileType : public ZoneAllocated {
bool IsNull();
// Return true if this type is a subtype of the given type.
bool IsSubtypeOf(NNBDMode mode, const AbstractType& other);
bool IsSubtypeOf(const AbstractType& other);
// Return true if value of this type is assignable to a location of the
// given type.
bool IsAssignableTo(NNBDMode mode, const AbstractType& type);
bool IsAssignableTo(const AbstractType& type);
// Create a new CompileType representing given combination of class id and
// abstract type. The pair is assumed to be coherent.

View file

@ -390,8 +390,7 @@ void ConstantPropagator::VisitAssertAssignable(AssertAssignableInstr* instr) {
} else if (IsConstant(value)) {
// We are ignoring the instantiator and instantiator_type_arguments, but
// still monotonic and safe.
if (instr->value()->Type()->IsAssignableTo(instr->nnbd_mode(),
instr->dst_type())) {
if (instr->value()->Type()->IsAssignableTo(instr->dst_type())) {
SetValue(instr, value);
} else {
SetValue(instr, non_constant_);
@ -829,9 +828,9 @@ void ConstantPropagator::VisitInstanceOf(InstanceOfInstr* instr) {
const Instance& instance = Instance::Cast(value);
if (instr->instantiator_type_arguments()->BindsToConstantNull() &&
instr->function_type_arguments()->BindsToConstantNull()) {
bool is_instance = instance.IsInstanceOf(
instr->nnbd_mode(), checked_type, Object::null_type_arguments(),
Object::null_type_arguments());
bool is_instance =
instance.IsInstanceOf(checked_type, Object::null_type_arguments(),
Object::null_type_arguments());
SetValue(instr, Bool::Get(is_instance));
return;
}

View file

@ -2295,7 +2295,7 @@ void FlowGraphCompiler::GenerateAssertAssignableViaTypeTestingStub(
// caller side!
const Type& int_type = Type::Handle(zone(), Type::IntType());
bool is_non_smi = false;
if (int_type.IsSubtypeOf(NNBDMode::kLegacyLib, dst_type, Heap::kOld)) {
if (int_type.IsSubtypeOf(dst_type, Heap::kOld)) {
__ BranchIfSmi(instance_reg, done);
is_non_smi = true;
}

View file

@ -552,7 +552,6 @@ class FlowGraphCompiler : public ValueObject {
intptr_t deopt_id,
const AbstractType& dst_type,
const String& dst_name,
NNBDMode mode,
LocationSummary* locs);
// Returns true if we can use a type testing stub based assert
@ -618,7 +617,6 @@ class FlowGraphCompiler : public ValueObject {
void GenerateInstanceOf(TokenPosition token_pos,
intptr_t deopt_id,
const AbstractType& type,
NNBDMode mode,
LocationSummary* locs);
void GenerateInstanceCall(intptr_t deopt_id,

View file

@ -279,8 +279,7 @@ FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
ASSERT(type_class.NumTypeArguments() > 0);
const Register kInstanceReg = R0;
const Type& smi_type = Type::Handle(zone(), Type::SmiType());
const bool smi_is_ok =
smi_type.IsSubtypeOf(NNBDMode::kLegacyLib, type, Heap::kOld);
const bool smi_is_ok = smi_type.IsSubtypeOf(type, Heap::kOld);
__ tst(kInstanceReg, compiler::Operand(kSmiTagMask));
if (smi_is_ok) {
// Fast case for type = FutureOr<int/num/top-type>.
@ -316,8 +315,7 @@ FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
ASSERT(tp_argument.HasTypeClass());
// Check if type argument is dynamic, Object, or void.
const Type& object_type = Type::Handle(zone(), Type::ObjectType());
if (object_type.IsSubtypeOf(NNBDMode::kLegacyLib, tp_argument,
Heap::kOld)) {
if (object_type.IsSubtypeOf(tp_argument, Heap::kOld)) {
// Instance class test only necessary.
return GenerateSubtype1TestCacheLookup(
token_pos, type_class, is_instance_lbl, is_not_instance_lbl);
@ -367,8 +365,8 @@ bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest(
__ tst(kInstanceReg, compiler::Operand(kSmiTagMask));
// If instance is Smi, check directly.
const Class& smi_class = Class::Handle(zone(), Smi::Class());
if (Class::IsSubtypeOf(NNBDMode::kLegacyLib, smi_class,
Object::null_type_arguments(), type, Heap::kOld)) {
if (Class::IsSubtypeOf(smi_class, Object::null_type_arguments(), type,
Heap::kOld)) {
// Fast case for type = int/num/top-type.
__ b(is_instance_lbl, EQ);
} else {
@ -615,7 +613,6 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateInlineInstanceof(
void FlowGraphCompiler::GenerateInstanceOf(TokenPosition token_pos,
intptr_t deopt_id,
const AbstractType& type,
NNBDMode mode,
LocationSummary* locs) {
ASSERT(type.IsFinalized());
ASSERT(!type.IsTopType()); // Already checked.
@ -660,11 +657,10 @@ void FlowGraphCompiler::GenerateInstanceOf(TokenPosition token_pos,
(1 << kFunctionTypeArgumentsReg));
__ LoadUniqueObject(R0, test_cache);
__ Push(R0);
__ PushImmediate(Smi::RawValue(static_cast<intptr_t>(mode)));
GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 6, locs);
GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs);
// Pop the parameters supplied to the runtime entry. The result of the
// instanceof runtime call will be left as the result of the operation.
__ Drop(6);
__ Drop(5);
__ Pop(R0);
__ b(&done);
}
@ -695,7 +691,6 @@ void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos,
intptr_t deopt_id,
const AbstractType& dst_type,
const String& dst_name,
NNBDMode mode,
LocationSummary* locs) {
ASSERT(!token_pos.IsClassifying());
ASSERT(!dst_type.IsNull());
@ -738,11 +733,10 @@ void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos,
__ LoadUniqueObject(R0, test_cache);
__ Push(R0);
__ PushImmediate(Smi::RawValue(kTypeCheckFromInline));
__ PushImmediate(Smi::RawValue(static_cast<intptr_t>(mode)));
GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 8, locs);
GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 7, locs);
// Pop the parameters supplied to the runtime entry. The result of the
// type check runtime call is the checked value.
__ Drop(8);
__ Drop(7);
__ Pop(R0);
__ Bind(&is_assignable);
__ PopList((1 << kFunctionTypeArgumentsReg) |

View file

@ -270,8 +270,7 @@ FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
ASSERT(type_class.NumTypeArguments() > 0);
const Register kInstanceReg = R0;
const Type& smi_type = Type::Handle(zone(), Type::SmiType());
const bool smi_is_ok =
smi_type.IsSubtypeOf(NNBDMode::kLegacyLib, type, Heap::kOld);
const bool smi_is_ok = smi_type.IsSubtypeOf(type, Heap::kOld);
// Fast case for type = FutureOr<int/num/top-type>.
__ BranchIfSmi(kInstanceReg,
smi_is_ok ? is_instance_lbl : is_not_instance_lbl);
@ -303,8 +302,7 @@ FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
if (tp_argument.IsType()) {
// Check if type argument is dynamic, Object, or void.
const Type& object_type = Type::Handle(zone(), Type::ObjectType());
if (object_type.IsSubtypeOf(NNBDMode::kLegacyLib, tp_argument,
Heap::kOld)) {
if (object_type.IsSubtypeOf(tp_argument, Heap::kOld)) {
// Instance class test only necessary.
return GenerateSubtype1TestCacheLookup(
token_pos, type_class, is_instance_lbl, is_not_instance_lbl);
@ -352,8 +350,8 @@ bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest(
const Register kInstanceReg = R0;
// If instance is Smi, check directly.
const Class& smi_class = Class::Handle(zone(), Smi::Class());
if (Class::IsSubtypeOf(NNBDMode::kLegacyLib, smi_class,
Object::null_type_arguments(), type, Heap::kOld)) {
if (Class::IsSubtypeOf(smi_class, Object::null_type_arguments(), type,
Heap::kOld)) {
// Fast case for type = int/num/top-type.
__ BranchIfSmi(kInstanceReg, is_instance_lbl);
} else {
@ -592,7 +590,6 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateInlineInstanceof(
void FlowGraphCompiler::GenerateInstanceOf(TokenPosition token_pos,
intptr_t deopt_id,
const AbstractType& type,
NNBDMode mode,
LocationSummary* locs) {
ASSERT(type.IsFinalized());
ASSERT(!type.IsTopType()); // Already checked.
@ -637,11 +634,10 @@ void FlowGraphCompiler::GenerateInstanceOf(TokenPosition token_pos,
__ PushPair(kInstantiatorTypeArgumentsReg, TMP);
__ LoadUniqueObject(R0, test_cache);
__ PushPair(R0, kFunctionTypeArgumentsReg);
__ PushImmediate(Smi::RawValue(static_cast<intptr_t>(mode)));
GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 6, locs);
GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs);
// Pop the parameters supplied to the runtime entry. The result of the
// instanceof runtime call will be left as the result of the operation.
__ Drop(6);
__ Drop(5);
__ Pop(R0);
__ b(&done);
}
@ -672,7 +668,6 @@ void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos,
intptr_t deopt_id,
const AbstractType& dst_type,
const String& dst_name,
NNBDMode mode,
LocationSummary* locs) {
ASSERT(!TokenPosition(token_pos).IsClassifying());
ASSERT(!dst_type.IsNull());
@ -714,11 +709,10 @@ void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos,
__ LoadUniqueObject(R0, test_cache);
__ LoadObject(TMP, Smi::ZoneHandle(zone(), Smi::New(kTypeCheckFromInline)));
__ PushPair(TMP, R0);
__ PushImmediate(Smi::RawValue(static_cast<intptr_t>(mode)));
GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 8, locs);
GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 7, locs);
// Pop the parameters supplied to the runtime entry. The result of the
// type check runtime call is the checked value.
__ Drop(8);
__ Drop(7);
__ Pop(R0);
__ Bind(&is_assignable);
__ PopPair(kFunctionTypeArgumentsReg, kInstantiatorTypeArgumentsReg);

View file

@ -258,8 +258,7 @@ FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
ASSERT(type_class.NumTypeArguments() > 0);
const Register kInstanceReg = EAX;
const Type& smi_type = Type::Handle(zone(), Type::SmiType());
const bool smi_is_ok =
smi_type.IsSubtypeOf(NNBDMode::kLegacyLib, type, Heap::kOld);
const bool smi_is_ok = smi_type.IsSubtypeOf(type, Heap::kOld);
__ testl(kInstanceReg, compiler::Immediate(kSmiTagMask));
if (smi_is_ok) {
// Fast case for type = FutureOr<int/num/top-type>.
@ -294,8 +293,7 @@ FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
if (tp_argument.IsType()) {
// Check if type argument is dynamic, Object, or void.
const Type& object_type = Type::Handle(zone(), Type::ObjectType());
if (object_type.IsSubtypeOf(NNBDMode::kLegacyLib, tp_argument,
Heap::kOld)) {
if (object_type.IsSubtypeOf(tp_argument, Heap::kOld)) {
// Instance class test only necessary.
return GenerateSubtype1TestCacheLookup(
token_pos, type_class, is_instance_lbl, is_not_instance_lbl);
@ -343,8 +341,8 @@ bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest(
__ testl(kInstanceReg, compiler::Immediate(kSmiTagMask));
// If instance is Smi, check directly.
const Class& smi_class = Class::Handle(zone(), Smi::Class());
if (Class::IsSubtypeOf(NNBDMode::kLegacyLib, smi_class,
Object::null_type_arguments(), type, Heap::kOld)) {
if (Class::IsSubtypeOf(smi_class, Object::null_type_arguments(), type,
Heap::kOld)) {
// Fast case for type = int/num/top-type.
__ j(ZERO, is_instance_lbl);
} else {
@ -594,7 +592,6 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateInlineInstanceof(
void FlowGraphCompiler::GenerateInstanceOf(TokenPosition token_pos,
intptr_t deopt_id,
const AbstractType& type,
NNBDMode mode,
LocationSummary* locs) {
ASSERT(type.IsFinalized());
ASSERT(!type.IsTopType()); // Already checked.
@ -640,12 +637,10 @@ void FlowGraphCompiler::GenerateInstanceOf(TokenPosition token_pos,
__ pushl(ECX); // Function type arguments.
__ LoadObject(EAX, test_cache);
__ pushl(EAX);
__ PushObject(
Smi::ZoneHandle(zone(), Smi::New(static_cast<intptr_t>(mode))));
GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 6, locs);
GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs);
// Pop the parameters supplied to the runtime entry. The result of the
// instanceof runtime call will be left as the result of the operation.
__ Drop(6);
__ Drop(5);
__ popl(EAX);
__ jmp(&done, compiler::Assembler::kNearJump);
}
@ -676,7 +671,6 @@ void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos,
intptr_t deopt_id,
const AbstractType& dst_type,
const String& dst_name,
NNBDMode mode,
LocationSummary* locs) {
ASSERT(!token_pos.IsClassifying());
ASSERT(!dst_type.IsNull());
@ -714,11 +708,10 @@ void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos,
__ LoadObject(EAX, test_cache);
__ pushl(EAX);
__ PushObject(Smi::ZoneHandle(zone(), Smi::New(kTypeCheckFromInline)));
__ PushObject(Smi::ZoneHandle(zone(), Smi::New(static_cast<intptr_t>(mode))));
GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 8, locs);
GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 7, locs);
// Pop the parameters supplied to the runtime entry. The result of the
// type check runtime call is the checked value.
__ Drop(8);
__ Drop(7);
__ popl(EAX);
__ Bind(&is_assignable);

View file

@ -276,8 +276,7 @@ FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
ASSERT(type_class.NumTypeArguments() > 0);
const Register kInstanceReg = RAX;
const Type& smi_type = Type::Handle(zone(), Type::SmiType());
const bool smi_is_ok =
smi_type.IsSubtypeOf(NNBDMode::kLegacyLib, type, Heap::kOld);
const bool smi_is_ok = smi_type.IsSubtypeOf(type, Heap::kOld);
__ testq(kInstanceReg, compiler::Immediate(kSmiTagMask));
if (smi_is_ok) {
// Fast case for type = FutureOr<int/num/top-type>.
@ -314,8 +313,7 @@ FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
ASSERT(tp_argument.HasTypeClass());
// Check if type argument is dynamic, Object, or void.
const Type& object_type = Type::Handle(zone(), Type::ObjectType());
if (object_type.IsSubtypeOf(NNBDMode::kLegacyLib, tp_argument,
Heap::kOld)) {
if (object_type.IsSubtypeOf(tp_argument, Heap::kOld)) {
// Instance class test only necessary.
return GenerateSubtype1TestCacheLookup(
token_pos, type_class, is_instance_lbl, is_not_instance_lbl);
@ -368,8 +366,8 @@ bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest(
__ testq(kInstanceReg, compiler::Immediate(kSmiTagMask));
// If instance is Smi, check directly.
const Class& smi_class = Class::Handle(zone(), Smi::Class());
if (Class::IsSubtypeOf(NNBDMode::kLegacyLib, smi_class,
Object::null_type_arguments(), type, Heap::kOld)) {
if (Class::IsSubtypeOf(smi_class, Object::null_type_arguments(), type,
Heap::kOld)) {
// Fast case for type = int/num/top-type.
__ j(ZERO, is_instance_lbl);
} else {
@ -617,7 +615,6 @@ RawSubtypeTestCache* FlowGraphCompiler::GenerateInlineInstanceof(
void FlowGraphCompiler::GenerateInstanceOf(TokenPosition token_pos,
intptr_t deopt_id,
const AbstractType& type,
NNBDMode mode,
LocationSummary* locs) {
ASSERT(type.IsFinalized());
ASSERT(!type.IsTopType()); // Already checked.
@ -655,12 +652,10 @@ void FlowGraphCompiler::GenerateInstanceOf(TokenPosition token_pos,
__ pushq(RCX); // Function type arguments.
__ LoadUniqueObject(RAX, test_cache);
__ pushq(RAX);
__ PushImmediate(
compiler::Immediate(Smi::RawValue(static_cast<intptr_t>(mode))));
GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 6, locs);
GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs);
// Pop the parameters supplied to the runtime entry. The result of the
// instanceof runtime call will be left as the result of the operation.
__ Drop(6);
__ Drop(5);
__ popq(RAX);
__ jmp(&done, compiler::Assembler::kNearJump);
}
@ -689,7 +684,6 @@ void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos,
intptr_t deopt_id,
const AbstractType& dst_type,
const String& dst_name,
NNBDMode mode,
LocationSummary* locs) {
ASSERT(!token_pos.IsClassifying());
ASSERT(!dst_type.IsNull());
@ -727,12 +721,10 @@ void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos,
__ LoadUniqueObject(RAX, test_cache);
__ pushq(RAX);
__ PushImmediate(compiler::Immediate(Smi::RawValue(kTypeCheckFromInline)));
__ PushImmediate(
compiler::Immediate(Smi::RawValue(static_cast<intptr_t>(mode))));
GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 8, locs);
GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 7, locs);
// Pop the parameters supplied to the runtime entry. The result of the
// type check runtime call is the checked value.
__ Drop(8);
__ Drop(7);
__ popq(RAX);
__ Bind(&is_assignable);
}

View file

@ -173,7 +173,6 @@ void HierarchyInfo::BuildRangesFor(ClassTable* table,
bool use_subtype_test,
bool include_abstract,
bool exclude_null) {
// TODO(regis): Does this function depend on NNBDMode?
Zone* zone = thread()->zone();
ClassTable* class_table = thread()->isolate()->class_table();
@ -214,8 +213,7 @@ void HierarchyInfo::BuildRangesFor(ClassTable* table,
test_succeeded = false;
} else if (use_subtype_test) {
cls_type = cls.RareType();
test_succeeded =
cls_type.IsSubtypeOf(NNBDMode::kLegacyLib, dst_type, Heap::kNew);
test_succeeded = cls_type.IsSubtypeOf(dst_type, Heap::kNew);
} else {
while (!cls.IsObjectClass()) {
if (cls.raw() == klass.raw()) {
@ -382,7 +380,7 @@ bool HierarchyInfo::CanUseSubtypeRangeCheckFor(const AbstractType& type) {
// arguments are not "dynamic" but instantiated-to-bounds.
const Type& rare_type =
Type::Handle(zone, Type::RawCast(type_class.RareType()));
if (!rare_type.IsSubtypeOf(NNBDMode::kLegacyLib, type, Heap::kNew)) {
if (!rare_type.IsSubtypeOf(type, Heap::kNew)) {
ASSERT(type.arguments() != TypeArguments::null());
return false;
}
@ -979,8 +977,7 @@ bool AssertAssignableInstr::AttributesEqual(Instruction* other) const {
ASSERT(other_assert != NULL);
// This predicate has to be commutative for DominatorBasedCSE to work.
// TODO(fschneider): Eliminate more asserts with subtype relation.
return dst_type().raw() == other_assert->dst_type().raw() &&
nnbd_mode() == other_assert->nnbd_mode();
return dst_type().raw() == other_assert->dst_type().raw();
}
Instruction* AssertSubtypeInstr::Canonicalize(FlowGraph* flow_graph) {
@ -1008,9 +1005,9 @@ Instruction* AssertSubtypeInstr::Canonicalize(FlowGraph* flow_graph) {
AbstractType& sub_type = AbstractType::Handle(Z, sub_type_.raw());
AbstractType& super_type = AbstractType::Handle(Z, super_type_.raw());
if (AbstractType::InstantiateAndTestSubtype(
nnbd_mode(), &sub_type, &super_type, instantiator_type_args,
function_type_args)) {
if (AbstractType::InstantiateAndTestSubtype(&sub_type, &super_type,
instantiator_type_args,
function_type_args)) {
return NULL;
}
}
@ -1021,8 +1018,7 @@ bool AssertSubtypeInstr::AttributesEqual(Instruction* other) const {
AssertSubtypeInstr* other_assert = other->AsAssertSubtype();
ASSERT(other_assert != NULL);
return super_type().raw() == other_assert->super_type().raw() &&
sub_type().raw() == other_assert->sub_type().raw() &&
nnbd_mode() == other_assert->nnbd_mode();
sub_type().raw() == other_assert->sub_type().raw();
}
bool StrictCompareInstr::AttributesEqual(Instruction* other) const {
@ -2867,7 +2863,7 @@ Definition* AssertBooleanInstr::Canonicalize(FlowGraph* flow_graph) {
Definition* AssertAssignableInstr::Canonicalize(FlowGraph* flow_graph) {
if (FLAG_eliminate_type_checks &&
value()->Type()->IsAssignableTo(nnbd_mode(), dst_type())) {
value()->Type()->IsAssignableTo(dst_type())) {
return value()->definition();
}
if (dst_type().IsInstantiated()) {
@ -2933,9 +2929,9 @@ Definition* AssertAssignableInstr::Canonicalize(FlowGraph* flow_graph) {
if ((instantiator_type_args != nullptr) && (function_type_args != nullptr)) {
AbstractType& new_dst_type = AbstractType::Handle(
Z, dst_type().InstantiateFrom(nnbd_mode(), *instantiator_type_args,
*function_type_args, kAllFree, nullptr,
Heap::kOld));
Z,
dst_type().InstantiateFrom(*instantiator_type_args, *function_type_args,
kAllFree, nullptr, Heap::kOld));
if (new_dst_type.IsNull()) {
// Failed instantiation in dead code.
return this;
@ -2954,7 +2950,7 @@ Definition* AssertAssignableInstr::Canonicalize(FlowGraph* flow_graph) {
if (new_dst_type.IsTopTypeForAssignability() ||
(FLAG_eliminate_type_checks &&
value()->Type()->IsAssignableTo(nnbd_mode(), new_dst_type))) {
value()->Type()->IsAssignableTo(new_dst_type))) {
return value()->definition();
}
}
@ -3240,8 +3236,7 @@ static bool MayBeNumber(CompileType* type) {
// Note that type 'Number' is a subtype of itself.
return unwrapped_type.IsTopType() || unwrapped_type.IsObjectType() ||
unwrapped_type.IsTypeParameter() ||
unwrapped_type.IsSubtypeOf(NNBDMode::kLegacyLib,
Type::Handle(Type::Number()), Heap::kOld);
unwrapped_type.IsSubtypeOf(Type::Handle(Type::Number()), Heap::kOld);
}
// Returns a replacement for a strict comparison and signals if the result has
@ -4245,12 +4240,8 @@ void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Register object = locs()->in(0).reg();
const Register result = locs()->out(0).reg();
const AbstractType& value_type = *this->object()->Type()->ToAbstractType();
// Using NNBDMode::kLegacyLib is safe, because it throws a wider
// net over the types accepting a Smi value, especially during the nnbd
// migration that does not guarantee soundness.
if (input_can_be_smi_ &&
(CompileType::Smi().IsAssignableTo(NNBDMode::kLegacyLib, value_type) ||
value_type.IsTypeParameter())) {
if (input_can_be_smi_ && (CompileType::Smi().IsAssignableTo(value_type) ||
value_type.IsTypeParameter())) {
if (representation() == kTagged) {
__ LoadTaggedClassIdMayBeSmi(result, object);
} else {
@ -4295,8 +4286,7 @@ void InstanceCallBaseInstr::UpdateReceiverSminess(Zone* zone) {
if (!interface_target().IsNull()) {
const AbstractType& target_type = AbstractType::Handle(
zone, Class::Handle(zone, interface_target().Owner()).RareType());
if (!CompileType::Smi().IsAssignableTo(NNBDMode::kLegacyLib,
target_type)) {
if (!CompileType::Smi().IsAssignableTo(target_type)) {
set_receiver_is_not_smi(true);
}
}
@ -4716,7 +4706,7 @@ intptr_t AssertAssignableInstr::statistics_tag() const {
void AssertAssignableInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
compiler->GenerateAssertAssignable(token_pos(), deopt_id(), dst_type(),
dst_name(), nnbd_mode(), locs());
dst_name(), locs());
ASSERT(locs()->in(0).reg() == locs()->out(0).reg());
}
@ -4729,12 +4719,11 @@ void AssertSubtypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ PushObject(sub_type());
__ PushObject(super_type());
__ PushObject(dst_name());
__ PushObject(Smi::ZoneHandle(Smi::New(static_cast<intptr_t>(nnbd_mode()))));
compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
kSubtypeCheckRuntimeEntry, 6, locs());
kSubtypeCheckRuntimeEntry, 5, locs());
__ Drop(6);
__ Drop(5);
}
LocationSummary* DeoptimizeInstr::MakeLocationSummary(Zone* zone,

View file

@ -3342,14 +3342,12 @@ class AssertSubtypeInstr : public TemplateInstruction<2, Throws, Pure> {
const AbstractType& sub_type,
const AbstractType& super_type,
const String& dst_name,
intptr_t deopt_id,
NNBDMode mode)
intptr_t deopt_id)
: TemplateInstruction(deopt_id),
token_pos_(token_pos),
sub_type_(AbstractType::ZoneHandle(sub_type.raw())),
super_type_(AbstractType::ZoneHandle(super_type.raw())),
dst_name_(String::ZoneHandle(dst_name.raw())),
nnbd_mode_(mode) {
dst_name_(String::ZoneHandle(dst_name.raw())) {
ASSERT(!super_type.IsNull());
ASSERT(!super_type.IsTypeRef());
ASSERT(!sub_type.IsNull());
@ -3368,7 +3366,6 @@ class AssertSubtypeInstr : public TemplateInstruction<2, Throws, Pure> {
const AbstractType& super_type() const { return super_type_; }
const AbstractType& sub_type() const { return sub_type_; }
const String& dst_name() const { return dst_name_; }
NNBDMode nnbd_mode() const { return nnbd_mode_; }
virtual bool ComputeCanDeoptimize() const { return !FLAG_precompiled_mode; }
@ -3385,7 +3382,6 @@ class AssertSubtypeInstr : public TemplateInstruction<2, Throws, Pure> {
AbstractType& sub_type_;
AbstractType& super_type_;
const String& dst_name_;
const NNBDMode nnbd_mode_;
DISALLOW_COPY_AND_ASSIGN(AssertSubtypeInstr);
};
@ -3412,13 +3408,11 @@ class AssertAssignableInstr : public TemplateDefinition<3, Throws, Pure> {
const AbstractType& dst_type,
const String& dst_name,
intptr_t deopt_id,
NNBDMode mode,
Kind kind = kUnknown)
: TemplateDefinition(deopt_id),
token_pos_(token_pos),
dst_type_(AbstractType::ZoneHandle(dst_type.raw())),
dst_name_(dst_name),
nnbd_mode_(mode),
kind_(kind) {
ASSERT(!dst_type.IsNull());
ASSERT(!dst_type.IsTypeRef());
@ -3446,7 +3440,6 @@ class AssertAssignableInstr : public TemplateDefinition<3, Throws, Pure> {
dst_type_ = dst_type.raw();
}
const String& dst_name() const { return dst_name_; }
NNBDMode nnbd_mode() const { return nnbd_mode_; }
virtual bool ComputeCanDeoptimize() const { return !FLAG_precompiled_mode; }
@ -3469,7 +3462,6 @@ class AssertAssignableInstr : public TemplateDefinition<3, Throws, Pure> {
const TokenPosition token_pos_;
AbstractType& dst_type_;
const String& dst_name_;
const NNBDMode nnbd_mode_;
const Kind kind_;
DISALLOW_COPY_AND_ASSIGN(AssertAssignableInstr);
@ -5430,12 +5422,8 @@ class InstanceOfInstr : public TemplateDefinition<3, Throws> {
Value* instantiator_type_arguments,
Value* function_type_arguments,
const AbstractType& type,
intptr_t deopt_id,
NNBDMode mode)
: TemplateDefinition(deopt_id),
token_pos_(token_pos),
type_(type),
nnbd_mode_(mode) {
intptr_t deopt_id)
: TemplateDefinition(deopt_id), token_pos_(token_pos), type_(type) {
ASSERT(!type.IsNull());
SetInputAt(0, value);
SetInputAt(1, instantiator_type_arguments);
@ -5451,7 +5439,6 @@ class InstanceOfInstr : public TemplateDefinition<3, Throws> {
const AbstractType& type() const { return type_; }
virtual TokenPosition token_pos() const { return token_pos_; }
NNBDMode nnbd_mode() const { return nnbd_mode_; }
virtual bool ComputeCanDeoptimize() const { return !FLAG_precompiled_mode; }
@ -5464,7 +5451,6 @@ class InstanceOfInstr : public TemplateDefinition<3, Throws> {
Value* value_;
Value* type_arguments_;
const AbstractType& type_;
const NNBDMode nnbd_mode_;
DISALLOW_COPY_AND_ASSIGN(InstanceOfInstr);
};
@ -5968,12 +5954,8 @@ class InstantiateTypeInstr : public TemplateDefinition<2, Throws> {
const AbstractType& type,
Value* instantiator_type_arguments,
Value* function_type_arguments,
intptr_t deopt_id,
NNBDMode mode)
: TemplateDefinition(deopt_id),
token_pos_(token_pos),
type_(type),
nnbd_mode_(mode) {
intptr_t deopt_id)
: TemplateDefinition(deopt_id), token_pos_(token_pos), type_(type) {
ASSERT(type.IsZoneHandle() || type.IsReadOnlyHandle());
SetInputAt(0, instantiator_type_arguments);
SetInputAt(1, function_type_arguments);
@ -5984,7 +5966,6 @@ class InstantiateTypeInstr : public TemplateDefinition<2, Throws> {
Value* instantiator_type_arguments() const { return inputs_[0]; }
Value* function_type_arguments() const { return inputs_[1]; }
const AbstractType& type() const { return type_; }
NNBDMode nnbd_mode() const { return nnbd_mode_; }
virtual TokenPosition token_pos() const { return token_pos_; }
virtual bool ComputeCanDeoptimize() const { return !FLAG_precompiled_mode; }
@ -5996,7 +5977,6 @@ class InstantiateTypeInstr : public TemplateDefinition<2, Throws> {
private:
const TokenPosition token_pos_;
const AbstractType& type_;
const NNBDMode nnbd_mode_;
DISALLOW_COPY_AND_ASSIGN(InstantiateTypeInstr);
};
@ -6009,14 +5989,12 @@ class InstantiateTypeArgumentsInstr : public TemplateDefinition<2, Throws> {
const Function& function,
Value* instantiator_type_arguments,
Value* function_type_arguments,
intptr_t deopt_id,
NNBDMode mode)
intptr_t deopt_id)
: TemplateDefinition(deopt_id),
token_pos_(token_pos),
type_arguments_(type_arguments),
instantiator_class_(instantiator_class),
function_(function),
nnbd_mode_(mode) {
function_(function) {
ASSERT(type_arguments.IsZoneHandle());
ASSERT(instantiator_class.IsZoneHandle());
ASSERT(function.IsZoneHandle());
@ -6031,7 +6009,6 @@ class InstantiateTypeArgumentsInstr : public TemplateDefinition<2, Throws> {
const TypeArguments& type_arguments() const { return type_arguments_; }
const Class& instantiator_class() const { return instantiator_class_; }
const Function& function() const { return function_; }
NNBDMode nnbd_mode() const { return nnbd_mode_; }
virtual TokenPosition token_pos() const { return token_pos_; }
virtual bool ComputeCanDeoptimize() const { return !FLAG_precompiled_mode; }
@ -6047,7 +6024,6 @@ class InstantiateTypeArgumentsInstr : public TemplateDefinition<2, Throws> {
const TypeArguments& type_arguments_;
const Class& instantiator_class_;
const Function& function_;
const NNBDMode nnbd_mode_;
DISALLOW_COPY_AND_ASSIGN(InstantiateTypeArgumentsInstr);
};

View file

@ -2875,8 +2875,7 @@ void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(locs()->in(1).reg() == R2); // Instantiator type arguments.
ASSERT(locs()->in(2).reg() == R1); // Function type arguments.
compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), nnbd_mode(),
locs());
compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs());
ASSERT(locs()->out(0).reg() == R0);
}
@ -3197,10 +3196,9 @@ void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ PushObject(type());
__ PushList((1 << instantiator_type_args_reg) |
(1 << function_type_args_reg));
__ PushImmediate(Smi::RawValue(static_cast<intptr_t>(nnbd_mode())));
compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
kInstantiateTypeRuntimeEntry, 4, locs());
__ Drop(4); // Drop mode, 2 type vectors, and uninstantiated type.
kInstantiateTypeRuntimeEntry, 3, locs());
__ Drop(3); // Drop 2 type vectors, and uninstantiated type.
__ Pop(result_reg); // Pop instantiated type.
}
@ -3264,11 +3262,6 @@ void InstantiateTypeArgumentsInstr::EmitNativeCode(
R3, TypeArguments::Instantiation::kFunctionTypeArgsIndex *
compiler::target::kWordSize));
__ cmp(IP, compiler::Operand(function_type_args_reg));
__ b(&next, NE);
__ ldr(IP,
compiler::Address(R3, TypeArguments::Instantiation::kNnbdModeIndex *
compiler::target::kWordSize));
__ CompareImmediate(IP, Smi::RawValue(static_cast<intptr_t>(nnbd_mode())));
__ b(&found, EQ);
__ Bind(&next);
__ AddImmediate(R3, TypeArguments::Instantiation::kSizeInWords *
@ -3290,11 +3283,10 @@ void InstantiateTypeArgumentsInstr::EmitNativeCode(
__ PushObject(type_arguments());
__ PushList((1 << instantiator_type_args_reg) |
(1 << function_type_args_reg));
__ PushImmediate(Smi::RawValue(static_cast<intptr_t>(nnbd_mode())));
compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
kInstantiateTypeArgumentsRuntimeEntry, 4,
kInstantiateTypeArgumentsRuntimeEntry, 3,
locs());
__ Drop(4); // Drop mode, 2 type vectors, and uninstantiated type.
__ Drop(3); // Drop 2 type vectors, and uninstantiated type.
__ Pop(result_reg); // Pop instantiated type arguments.
__ Bind(&type_arguments_instantiated);
}

View file

@ -2432,8 +2432,7 @@ void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(locs()->in(1).reg() == R1); // Instantiator type arguments.
ASSERT(locs()->in(2).reg() == R2); // Function type arguments.
compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), nnbd_mode(),
locs());
compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs());
ASSERT(locs()->out(0).reg() == R0);
}
@ -2730,10 +2729,9 @@ void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ LoadObject(TMP, type());
__ PushPair(TMP, NULL_REG);
__ PushPair(function_type_args_reg, instantiator_type_args_reg);
__ PushImmediate(Smi::RawValue(static_cast<intptr_t>(nnbd_mode())));
compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
kInstantiateTypeRuntimeEntry, 4, locs());
__ Drop(4); // Drop mode, 2 type vectors, and uninstantiated type.
kInstantiateTypeRuntimeEntry, 3, locs());
__ Drop(3); // Drop 2 type vectors, and uninstantiated type.
__ Pop(result_reg); // Pop instantiated type.
ASSERT(instantiator_type_args_reg == result_reg);
}
@ -2798,10 +2796,6 @@ void InstantiateTypeArgumentsInstr::EmitNativeCode(
TMP, R3,
TypeArguments::Instantiation::kFunctionTypeArgsIndex * kWordSize);
__ CompareRegisters(TMP, function_type_args_reg);
__ b(&next, NE);
__ LoadFromOffset(TMP, R3,
TypeArguments::Instantiation::kNnbdModeIndex * kWordSize);
__ CompareImmediate(TMP, Smi::RawValue(static_cast<intptr_t>(nnbd_mode())));
__ b(&found, EQ);
__ Bind(&next);
__ AddImmediate(R3, TypeArguments::Instantiation::kSizeInWords * kWordSize);
@ -2820,11 +2814,10 @@ void InstantiateTypeArgumentsInstr::EmitNativeCode(
__ LoadObject(TMP, type_arguments());
__ PushPair(TMP, NULL_REG);
__ PushPair(function_type_args_reg, instantiator_type_args_reg);
__ PushImmediate(Smi::RawValue(static_cast<intptr_t>(nnbd_mode())));
compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
kInstantiateTypeArgumentsRuntimeEntry, 4,
kInstantiateTypeArgumentsRuntimeEntry, 3,
locs());
__ Drop(4); // Drop mode, 2 type vectors, and uninstantiated type.
__ Drop(3); // Drop 2 type vectors, and uninstantiated type.
__ Pop(result_reg); // Pop instantiated type arguments.
__ Bind(&type_arguments_instantiated);
}

View file

@ -893,9 +893,6 @@ AssertAssignableInstr* FlowGraphDeserializer::DeserializeAssertAssignable(
auto const dst_name_sexp = Retrieve(sexp, "name");
if (!ParseDartValue(dst_name_sexp, &dst_name)) return nullptr;
// TODO(regis): Serialize/deserialize nnbd_mode.
auto nnbd_mode = NNBDMode::kLegacyLib;
auto kind = AssertAssignableInstr::Kind::kUnknown;
if (auto const kind_sexp = CheckSymbol(sexp->ExtraLookupValue("kind"))) {
if (!AssertAssignableInstr::ParseKind(kind_sexp->value(), &kind)) {
@ -906,7 +903,7 @@ AssertAssignableInstr* FlowGraphDeserializer::DeserializeAssertAssignable(
return new (zone())
AssertAssignableInstr(info.token_pos, val, inst_type_args, func_type_args,
dst_type, dst_name, info.deopt_id, nnbd_mode, kind);
dst_type, dst_name, info.deopt_id, kind);
}
AssertBooleanInstr* FlowGraphDeserializer::DeserializeAssertBoolean(

View file

@ -2225,8 +2225,7 @@ void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(locs()->in(1).reg() == EDX); // Instantiator type arguments.
ASSERT(locs()->in(2).reg() == ECX); // Function type arguments.
compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), nnbd_mode(),
locs());
compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs());
ASSERT(locs()->out(0).reg() == EAX);
}
@ -2491,11 +2490,9 @@ void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ PushObject(type());
__ pushl(instantiator_type_args_reg); // Push instantiator type arguments.
__ pushl(function_type_args_reg); // Push function type arguments.
__ pushl(compiler::Immediate(
reinterpret_cast<int32_t>(Smi::New(static_cast<intptr_t>(nnbd_mode())))));
compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
kInstantiateTypeRuntimeEntry, 4, locs());
__ Drop(4); // Drop mode, 2 type vectors, and uninstantiated type.
kInstantiateTypeRuntimeEntry, 3, locs());
__ Drop(3); // Drop 2 type vectors, and uninstantiated type.
__ popl(result_reg); // Pop instantiated type.
ASSERT(instantiator_type_args_reg == result_reg);
}
@ -2563,12 +2560,6 @@ void InstantiateTypeArgumentsInstr::EmitNativeCode(
EDI, TypeArguments::Instantiation::kFunctionTypeArgsIndex *
kWordSize));
__ cmpl(EBX, function_type_args_reg);
__ j(NOT_EQUAL, &next, compiler::Assembler::kNearJump);
__ movl(EBX,
compiler::Address(
EDI, TypeArguments::Instantiation::kNnbdModeIndex * kWordSize));
__ cmpl(EBX, compiler::Immediate(
Smi::RawValue(static_cast<intptr_t>(nnbd_mode()))));
__ j(EQUAL, &found, compiler::Assembler::kNearJump);
__ Bind(&next);
__ addl(EDI, compiler::Immediate(TypeArguments::Instantiation::kSizeInWords *
@ -2591,12 +2582,10 @@ void InstantiateTypeArgumentsInstr::EmitNativeCode(
__ PushObject(type_arguments());
__ pushl(instantiator_type_args_reg); // Push instantiator type arguments.
__ pushl(function_type_args_reg); // Push function type arguments.
__ pushl(
compiler::Immediate(Smi::RawValue(static_cast<intptr_t>(nnbd_mode()))));
compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
kInstantiateTypeArgumentsRuntimeEntry, 4,
kInstantiateTypeArgumentsRuntimeEntry, 3,
locs());
__ Drop(4); // Drop mode, 2 type vectors, and uninstantiated args.
__ Drop(3); // Drop 2 type vectors, and uninstantiated args.
__ popl(result_reg); // Pop instantiated type arguments.
__ Bind(&type_arguments_instantiated);
}

View file

@ -2414,8 +2414,7 @@ void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(locs()->in(1).reg() == RDX); // Instantiator type arguments.
ASSERT(locs()->in(2).reg() == RCX); // Function type arguments.
compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), nnbd_mode(),
locs());
compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs());
ASSERT(locs()->out(0).reg() == RAX);
}
@ -2726,11 +2725,9 @@ void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ PushObject(type());
__ pushq(instantiator_type_args_reg); // Push instantiator type arguments.
__ pushq(function_type_args_reg); // Push function type arguments.
__ PushImmediate(
compiler::Immediate(Smi::RawValue(static_cast<intptr_t>(nnbd_mode()))));
compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
kInstantiateTypeRuntimeEntry, 4, locs());
__ Drop(4); // Drop mode, 2 type vectors, and uninstantiated type.
kInstantiateTypeRuntimeEntry, 3, locs());
__ Drop(3); // Drop 2 type vectors, and uninstantiated type.
__ popq(result_reg); // Pop instantiated type.
}
@ -2796,12 +2793,6 @@ void InstantiateTypeArgumentsInstr::EmitNativeCode(
RDI, TypeArguments::Instantiation::kFunctionTypeArgsIndex *
kWordSize));
__ cmpq(R10, function_type_args_reg);
__ j(NOT_EQUAL, &next, compiler::Assembler::kNearJump);
__ movq(R10,
compiler::Address(
RDI, TypeArguments::Instantiation::kNnbdModeIndex * kWordSize));
__ cmpq(R10, compiler::Immediate(
Smi::RawValue(static_cast<intptr_t>(nnbd_mode()))));
__ j(EQUAL, &found, compiler::Assembler::kNearJump);
__ Bind(&next);
__ addq(RDI, compiler::Immediate(TypeArguments::Instantiation::kSizeInWords *
@ -2824,12 +2815,10 @@ void InstantiateTypeArgumentsInstr::EmitNativeCode(
__ PushObject(type_arguments());
__ pushq(instantiator_type_args_reg); // Push instantiator type arguments.
__ pushq(function_type_args_reg); // Push function type arguments.
__ PushImmediate(
compiler::Immediate(Smi::RawValue(static_cast<intptr_t>(nnbd_mode()))));
compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
kInstantiateTypeArgumentsRuntimeEntry, 4,
kInstantiateTypeArgumentsRuntimeEntry, 3,
locs());
__ Drop(4); // Drop mode, 2 type vectors, and uninstantiated type.
__ Drop(3); // Drop 2 type vectors, and uninstantiated type.
__ popq(result_reg); // Pop instantiated type arguments.
__ Bind(&type_arguments_instantiated);
}

View file

@ -2600,7 +2600,7 @@ static bool InlineSetIndexed(FlowGraph* flow_graph,
token_pos, new (Z) Value(stored_value), new (Z) Value(type_args),
new (Z)
Value(flow_graph->constant_null()), // Function type arguments.
value_type, Symbols::Value(), call->deopt_id(), target.nnbd_mode());
value_type, Symbols::Value(), call->deopt_id());
cursor = flow_graph->AppendTo(cursor, assert_value, call->env(),
FlowGraph::kValue);
}

View file

@ -364,8 +364,7 @@ static Definition* MakeAssertAssignable(CompilerState* S,
new Value(flow_graph->constant_null()),
new Value(flow_graph->constant_null()),
AbstractType::ZoneHandle(Type::ObjectType()),
Symbols::Empty(), S->GetNextDeoptId(),
NNBDMode::kLegacyLib);
Symbols::Empty(), S->GetNextDeoptId());
}
ISOLATE_UNIT_TEST_CASE(LoadOptimizer_RedefinitionAliasing_CheckNull_NoEscape) {

View file

@ -556,12 +556,10 @@ void CompileType::Union(CompileType* other) {
}
const AbstractType* other_abstract_type = other->ToAbstractType();
if (abstract_type->IsSubtypeOf(NNBDMode::kLegacyLib, *other_abstract_type,
Heap::kOld)) {
if (abstract_type->IsSubtypeOf(*other_abstract_type, Heap::kOld)) {
type_ = other_abstract_type;
return;
} else if (other_abstract_type->IsSubtypeOf(NNBDMode::kLegacyLib,
*abstract_type, Heap::kOld)) {
} else if (other_abstract_type->IsSubtypeOf(*abstract_type, Heap::kOld)) {
return; // Nothing to do.
}
@ -571,8 +569,7 @@ void CompileType::Union(CompileType* other) {
Class& cls = Class::Handle(abstract_type->type_class());
for (; !cls.IsNull() && !cls.IsGeneric(); cls = cls.SuperClass()) {
type_ = &AbstractType::ZoneHandle(cls.RareType());
if (other_abstract_type->IsSubtypeOf(NNBDMode::kLegacyLib, *type_,
Heap::kOld)) {
if (other_abstract_type->IsSubtypeOf(*type_, Heap::kOld)) {
// Found suitable supertype: keep type_ only.
cid_ = kDynamicCid;
return;
@ -612,8 +609,7 @@ CompileType* CompileType::ComputeRefinedType(CompileType* old_type,
const AbstractType* new_abstract_type = new_type->ToAbstractType();
CompileType* preferred_type;
if (old_abstract_type->IsSubtypeOf(NNBDMode::kLegacyLib, *new_abstract_type,
Heap::kOld)) {
if (old_abstract_type->IsSubtypeOf(*new_abstract_type, Heap::kOld)) {
// Prefer old type, as it is clearly more specific.
preferred_type = old_type;
} else {
@ -800,10 +796,10 @@ bool CompileType::IsNotSmi() {
// TODO(sjindel): Use instantiate-to-bounds instead.
if (!type->IsInstantiated()) return false;
const AbstractType& smi = AbstractType::Handle(Type::SmiType());
return !smi.IsSubtypeOf(NNBDMode::kLegacyLib, *type, Heap::Space::kNew);
return !smi.IsSubtypeOf(*type, Heap::Space::kNew);
}
bool CompileType::IsSubtypeOf(NNBDMode mode, const AbstractType& other) {
bool CompileType::IsSubtypeOf(const AbstractType& other) {
if (other.IsTopType()) {
return true;
}
@ -812,10 +808,10 @@ bool CompileType::IsSubtypeOf(NNBDMode mode, const AbstractType& other) {
return false;
}
return ToAbstractType()->IsSubtypeOf(mode, other, Heap::kOld);
return ToAbstractType()->IsSubtypeOf(other, Heap::kOld);
}
bool CompileType::IsAssignableTo(NNBDMode mode, const AbstractType& other) {
bool CompileType::IsAssignableTo(const AbstractType& other) {
if (other.IsTopTypeForAssignability()) {
return true;
}
@ -829,7 +825,7 @@ bool CompileType::IsAssignableTo(NNBDMode mode, const AbstractType& other) {
if (compile_type.IsNullType()) {
return Instance::NullIsAssignableTo(other);
}
return compile_type.IsSubtypeOf(mode, other, Heap::kOld);
return compile_type.IsSubtypeOf(other, Heap::kOld);
}
bool CompileType::Specialize(GrowableArray<intptr_t>* class_ids) {
@ -926,7 +922,6 @@ bool PhiInstr::RecomputeType() {
}
CompileType RedefinitionInstr::ComputeType() const {
// TODO(regis): Revisit for NNBD support.
if (constrained_type_ != NULL) {
// Check if the type associated with this redefinition is more specific
// than the type of its input. If yes, return it. Otherwise, fall back
@ -945,8 +940,7 @@ CompileType RedefinitionInstr::ComputeType() const {
return CompileType::CreateNullable(is_nullable,
constrained_type_->ToNullableCid());
}
if (value()->Type()->IsSubtypeOf(NNBDMode::kLegacyLib,
*constrained_type_->ToAbstractType())) {
if (value()->Type()->IsSubtypeOf(*constrained_type_->ToAbstractType())) {
return is_nullable ? *value()->Type()
: value()->Type()->CopyNonNullable();
} else {
@ -1163,7 +1157,7 @@ CompileType ConstantInstr::ComputeType() const {
CompileType AssertAssignableInstr::ComputeType() const {
CompileType* value_type = value()->Type();
if (value_type->IsSubtypeOf(nnbd_mode(), dst_type())) {
if (value_type->IsSubtypeOf(dst_type())) {
return *value_type;
}

View file

@ -897,14 +897,14 @@ bool CallSpecializer::TryInlineInstanceSetter(InstanceCallInstr* instr) {
}
}
InsertBefore(instr,
new (Z) AssertAssignableInstr(
instr->token_pos(), new (Z) Value(instr->ArgumentAt(1)),
new (Z) Value(instantiator_type_args),
new (Z) Value(function_type_args), dst_type,
String::ZoneHandle(zone(), field.name()),
instr->deopt_id(), target.nnbd_mode()),
instr->env(), FlowGraph::kEffect);
InsertBefore(
instr,
new (Z) AssertAssignableInstr(
instr->token_pos(), new (Z) Value(instr->ArgumentAt(1)),
new (Z) Value(instantiator_type_args),
new (Z) Value(function_type_args), dst_type,
String::ZoneHandle(zone(), field.name()), instr->deopt_id()),
instr->env(), FlowGraph::kEffect);
}
}
@ -1061,7 +1061,6 @@ bool CallSpecializer::TryInlineInstanceMethod(InstanceCallInstr* call) {
// An instance-of test returning all same results can be converted to a class
// check.
RawBool* CallSpecializer::InstanceOfAsBool(
NNBDMode mode,
const ICData& ic_data,
const AbstractType& type,
ZoneGrowableArray<intptr_t>* results) const {
@ -1110,8 +1109,8 @@ RawBool* CallSpecializer::InstanceOfAsBool(
is_subtype = unwrapped_type.IsTopType() || unwrapped_type.IsNullable() ||
(unwrapped_type.IsLegacy() && unwrapped_type.IsNeverType());
} else {
is_subtype = Class::IsSubtypeOf(mode, cls, Object::null_type_arguments(),
type, Heap::kOld);
is_subtype = Class::IsSubtypeOf(cls, Object::null_type_arguments(), type,
Heap::kOld);
}
results->Add(cls.id());
results->Add(static_cast<intptr_t>(is_subtype));
@ -1127,8 +1126,7 @@ RawBool* CallSpecializer::InstanceOfAsBool(
}
// Returns true if checking against this type is a direct class id comparison.
bool CallSpecializer::TypeCheckAsClassEquality(NNBDMode mode,
const AbstractType& type) {
bool CallSpecializer::TypeCheckAsClassEquality(const AbstractType& type) {
ASSERT(type.IsFinalized());
// Requires CHA.
if (!type.IsInstantiated()) return false;
@ -1192,7 +1190,6 @@ bool CallSpecializer::TryReplaceInstanceOfWithRangeCheck(
}
bool CallSpecializer::TryOptimizeInstanceOfUsingStaticTypes(
NNBDMode mode,
InstanceCallInstr* call,
const AbstractType& type) {
ASSERT(I->can_use_strong_mode_types());
@ -1223,7 +1220,7 @@ bool CallSpecializer::TryOptimizeInstanceOfUsingStaticTypes(
// If the static type of the receiver is a subtype of the tested type,
// replace 'receiver is type' with 'receiver == null' if type is Null
// or with 'receiver != null' otherwise.
if (left_value->Type()->IsSubtypeOf(mode, type)) {
if (left_value->Type()->IsSubtypeOf(type)) {
Definition* replacement = new (Z) StrictCompareInstr(
call->token_pos(),
(unwrapped_type.IsNullType() || unwrapped_type.IsNeverType())
@ -1251,33 +1248,25 @@ void CallSpecializer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
Definition* instantiator_type_args = NULL;
Definition* function_type_args = NULL;
AbstractType& type = AbstractType::ZoneHandle(Z);
NNBDMode nnbd_mode;
ASSERT(call->type_args_len() == 0);
if (call->ArgumentCount() == 2) {
instantiator_type_args = flow_graph()->constant_null();
function_type_args = flow_graph()->constant_null();
ASSERT(call->MatchesCoreName(Symbols::_simpleInstanceOf()));
type = AbstractType::Cast(call->ArgumentAt(1)->AsConstant()->value()).raw();
// Since type literals are not imported, a legacy type indicates that the
// call originated in a legacy library. Note that the type test against a
// non-legacy type (even in a legacy library) such as dynamic, void, or Null
// yield the same result independently of the mode used.
nnbd_mode = type.IsLegacy() ? NNBDMode::kLegacyLib : NNBDMode::kOptedInLib;
} else {
ASSERT(call->ArgumentCount() == 5);
ASSERT(call->ArgumentCount() == 4);
instantiator_type_args = call->ArgumentAt(1);
function_type_args = call->ArgumentAt(2);
type = AbstractType::Cast(call->ArgumentAt(3)->AsConstant()->value()).raw();
nnbd_mode = static_cast<NNBDMode>(
Smi::Cast(call->ArgumentAt(4)->AsConstant()->value()).Value());
}
if (I->can_use_strong_mode_types() &&
TryOptimizeInstanceOfUsingStaticTypes(nnbd_mode, call, type)) {
TryOptimizeInstanceOfUsingStaticTypes(call, type)) {
return;
}
if (TypeCheckAsClassEquality(nnbd_mode, type)) {
if (TypeCheckAsClassEquality(type)) {
LoadClassIdInstr* left_cid = new (Z) LoadClassIdInstr(new (Z) Value(left));
InsertBefore(call, left_cid, NULL, FlowGraph::kValue);
const intptr_t type_cid = Class::Handle(Z, type.type_class()).id();
@ -1301,8 +1290,8 @@ void CallSpecializer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
if (number_of_checks > 0 && number_of_checks <= FLAG_max_polymorphic_checks) {
ZoneGrowableArray<intptr_t>* results =
new (Z) ZoneGrowableArray<intptr_t>(number_of_checks * 2);
const Bool& as_bool = Bool::ZoneHandle(
Z, InstanceOfAsBool(nnbd_mode, unary_checks, type, results));
const Bool& as_bool =
Bool::ZoneHandle(Z, InstanceOfAsBool(unary_checks, type, results));
if (as_bool.IsNull() || FLAG_precompiled_mode) {
if (results->length() == number_of_checks * 2) {
const bool can_deopt = SpecializeTestCidsForNumericTypes(results, type);
@ -1333,7 +1322,7 @@ void CallSpecializer::ReplaceWithInstanceOf(InstanceCallInstr* call) {
InstanceOfInstr* instance_of = new (Z) InstanceOfInstr(
call->token_pos(), new (Z) Value(left),
new (Z) Value(instantiator_type_args), new (Z) Value(function_type_args),
type, call->deopt_id(), nnbd_mode);
type, call->deopt_id());
ReplaceCall(call, instance_of);
}
@ -1458,9 +1447,8 @@ bool CallSpecializer::SpecializeTestCidsForNumericTypes(
const ClassTable& class_table = *Isolate::Current()->class_table();
if ((*results)[0] != kSmiCid) {
const Class& smi_class = Class::Handle(class_table.At(kSmiCid));
const bool smi_is_subtype =
Class::IsSubtypeOf(NNBDMode::kLegacyLib, smi_class,
Object::null_type_arguments(), type, Heap::kOld);
const bool smi_is_subtype = Class::IsSubtypeOf(
smi_class, Object::null_type_arguments(), type, Heap::kOld);
results->Add((*results)[results->length() - 2]);
results->Add((*results)[results->length() - 2]);
for (intptr_t i = results->length() - 3; i > 1; --i) {
@ -1587,9 +1575,7 @@ void TypedDataSpecializer::TryInlineCall(TemplateDartCall<0>* call) {
auto& type_class = Class::Handle(zone_);
#define TRY_INLINE(iface, member_name, type, cid) \
if (!member_name.IsNull()) { \
const NNBDMode mode = \
member_name.IsLegacy() ? NNBDMode::kLegacyLib : NNBDMode::kOptedInLib; \
if (receiver_type->IsAssignableTo(mode, member_name)) { \
if (receiver_type->IsAssignableTo(member_name)) { \
if (is_length_getter) { \
type_class = member_name.type_class(); \
ReplaceWithLengthGetter(call); \
@ -1599,7 +1585,7 @@ void TypedDataSpecializer::TryInlineCall(TemplateDartCall<0>* call) {
ReplaceWithIndexGet(call, cid); \
} else { \
if (!index_type->IsNullableInt()) return; \
if (!value_type->IsAssignableTo(mode, type)) return; \
if (!value_type->IsAssignableTo(type)) return; \
type_class = member_name.type_class(); \
ReplaceWithIndexSet(call, cid); \
} \

View file

@ -134,7 +134,7 @@ class CallSpecializer : public FlowGraphVisitor {
const bool should_clone_fields_;
private:
bool TypeCheckAsClassEquality(NNBDMode mode, const AbstractType& type);
bool TypeCheckAsClassEquality(const AbstractType& type);
// Insert a Smi check if needed.
void AddCheckSmi(Definition* to_check,
@ -155,13 +155,11 @@ class CallSpecializer : public FlowGraphVisitor {
bool TryInlineImplicitInstanceGetter(InstanceCallInstr* call);
RawBool* InstanceOfAsBool(NNBDMode mode,
const ICData& ic_data,
RawBool* InstanceOfAsBool(const ICData& ic_data,
const AbstractType& type,
ZoneGrowableArray<intptr_t>* results) const;
bool TryOptimizeInstanceOfUsingStaticTypes(NNBDMode mode,
InstanceCallInstr* call,
bool TryOptimizeInstanceOfUsingStaticTypes(InstanceCallInstr* call,
const AbstractType& type);
void ReplaceWithMathCFunction(InstanceCallInstr* call,

View file

@ -854,7 +854,7 @@ Fragment BaseFlowGraphBuilder::InstantiateType(const AbstractType& type) {
Value* instantiator_type_args = Pop();
InstantiateTypeInstr* instr = new (Z) InstantiateTypeInstr(
TokenPosition::kNoSource, type, instantiator_type_args,
function_type_args, GetNextDeoptId(), nnbd_mode());
function_type_args, GetNextDeoptId());
Push(instr);
return Fragment(instr);
}
@ -866,8 +866,7 @@ Fragment BaseFlowGraphBuilder::InstantiateTypeArguments(
const Class& instantiator_class = Class::ZoneHandle(Z, function_.Owner());
InstantiateTypeArgumentsInstr* instr = new (Z) InstantiateTypeArgumentsInstr(
TokenPosition::kNoSource, type_arguments, instantiator_class, function_,
instantiator_type_args, function_type_args, GetNextDeoptId(),
nnbd_mode());
instantiator_type_args, function_type_args, GetNextDeoptId());
Push(instr);
return Fragment(instr);
}
@ -1090,7 +1089,7 @@ Fragment BaseFlowGraphBuilder::AssertAssignable(
AssertAssignableInstr* instr = new (Z) AssertAssignableInstr(
position, value, instantiator_type_args, function_type_args, dst_type,
dst_name, GetNextDeoptId(), nnbd_mode(), kind);
dst_name, GetNextDeoptId(), kind);
Push(instr);
return Fragment(instr);

View file

@ -410,9 +410,6 @@ class BaseFlowGraphBuilder {
// Sets raw parameter variables to inferred constant values.
Fragment InitConstantParameters();
// The NNBD mode to use when compiling type tests.
NNBDMode nnbd_mode() const { return function_.nnbd_mode(); }
protected:
intptr_t AllocateBlockId() { return ++last_used_block_id_; }

View file

@ -916,7 +916,7 @@ static void ComputeTokenKindAndCheckedArguments(
*checked_argument_count = 2;
*token_kind = Token::kIS;
} else if (Library::IsPrivateCoreLibName(name, Symbols::_instanceOf())) {
ASSERT(arg_desc.Count() == 5);
ASSERT(arg_desc.Count() == 4);
*token_kind = Token::kIS;
}
}
@ -1378,7 +1378,7 @@ void BytecodeFlowGraphBuilder::BuildAssertAssignable() {
AssertAssignableInstr* instr = new (Z) AssertAssignableInstr(
position_, value, instantiator_type_args, function_type_args, dst_type,
dst_name, B->GetNextDeoptId(), nnbd_mode());
dst_name, B->GetNextDeoptId());
code_ <<= instr;
@ -1398,9 +1398,9 @@ void BytecodeFlowGraphBuilder::BuildAssertSubtype() {
Value* function_type_args = Pop();
Value* instantiator_type_args = Pop();
AssertSubtypeInstr* instr = new (Z) AssertSubtypeInstr(
position_, instantiator_type_args, function_type_args, sub_type,
super_type, dst_name, B->GetNextDeoptId(), nnbd_mode());
AssertSubtypeInstr* instr = new (Z)
AssertSubtypeInstr(position_, instantiator_type_args, function_type_args,
sub_type, super_type, dst_name, B->GetNextDeoptId());
code_ <<= instr;
}

View file

@ -208,9 +208,6 @@ class BytecodeFlowGraphBuilder {
}
const Function& function() const { return parsed_function()->function(); }
// The NNBD mode to use when compiling type tests.
NNBDMode nnbd_mode() const { return function().nnbd_mode(); }
BaseFlowGraphBuilder* flow_graph_builder_;
Zone* zone_;
bool is_generating_interpreter_;

View file

@ -1636,8 +1636,8 @@ Function& StreamingFlowGraphBuilder::FindMatchingFunction(
while (!iterate_klass.IsNull()) {
function = iterate_klass.LookupDynamicFunctionAllowPrivate(name);
if (!function.IsNull()) {
if (function.AreValidArguments(NNBDMode::kLegacyLib, type_args_len,
argument_count, argument_names,
if (function.AreValidArguments(type_args_len, argument_count,
argument_names,
/* error_message = */ NULL)) {
return function;
}
@ -3335,8 +3335,8 @@ Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(TokenPosition* p) {
instructions +=
BuildArguments(&argument_names, NULL /* arg count */,
NULL /* positional arg count */); // read arguments.
ASSERT(target.AreValidArguments(NNBDMode::kLegacyLib, type_args_len,
argument_count, argument_names, NULL));
ASSERT(target.AreValidArguments(type_args_len, argument_count, argument_names,
NULL));
// Special case identical(x, y) call.
// Note: similar optimization is performed in bytecode flow graph builder -
@ -3620,14 +3620,10 @@ Fragment StreamingFlowGraphBuilder::BuildIsExpression(TokenPosition* p) {
TokenPosition position = ReadPosition(); // read position.
if (p != NULL) *p = position;
NNBDMode nnbd_mode;
if (translation_helper_.info().kernel_binary_version() >= 38) {
const uint8_t flags = ReadFlags(); // read flags.
nnbd_mode = ((flags & kIsExpressionFlagForNonNullableByDefault) != 0)
? NNBDMode::kOptedInLib
: NNBDMode::kLegacyLib;
} else {
nnbd_mode = NNBDMode::kLegacyLib;
// We do not use the library mode for the type test, which is indicated by
// the flag kIsExpressionFlagForNonNullableByDefault.
ReadFlags();
}
Fragment instructions = BuildExpression(); // read operand.
@ -3666,11 +3662,9 @@ Fragment StreamingFlowGraphBuilder::BuildIsExpression(TokenPosition* p) {
instructions += Constant(type);
instructions += IntConstant(static_cast<intptr_t>(nnbd_mode));
instructions += InstanceCall(
position, Library::PrivateCoreLibName(Symbols::_instanceOf()),
Token::kIS, 5);
Token::kIS, 4);
}
return instructions;
}
@ -4785,12 +4779,9 @@ Fragment StreamingFlowGraphBuilder::BuildTryCatch() {
catch_body += Constant(*type_guard);
const NNBDMode nnbd_mode = parsed_function()->function().nnbd_mode();
catch_body += IntConstant(static_cast<intptr_t>(nnbd_mode));
catch_body += InstanceCall(
position, Library::PrivateCoreLibName(Symbols::_instanceOf()),
Token::kIS, 5);
Token::kIS, 4);
TargetEntryInstr* catch_entry;
TargetEntryInstr* next_catch_entry;

View file

@ -1638,9 +1638,9 @@ Fragment FlowGraphBuilder::AssertSubtype(TokenPosition position,
instructions += LoadFunctionTypeArguments();
Value* function_type_args = Pop();
AssertSubtypeInstr* instr = new (Z) AssertSubtypeInstr(
position, instantiator_type_args, function_type_args, sub_type,
super_type, dst_name, GetNextDeoptId(), nnbd_mode());
AssertSubtypeInstr* instr = new (Z)
AssertSubtypeInstr(position, instantiator_type_args, function_type_args,
sub_type, super_type, dst_name, GetNextDeoptId());
instructions += Fragment(instr);
return instructions;

View file

@ -3002,11 +3002,8 @@ static void InvokeTypeCheckFromTypeTestStub(Assembler* assembler,
__ PushObject(NullObject());
__ Push(kSubtypeTestCacheReg);
__ PushImmediate(target::ToRawSmi(mode));
// TODO(regis): Pass nnbd mode in a register from call site.
__ PushImmediate(
target::ToRawSmi(static_cast<intptr_t>(NNBDMode::kLegacyLib)));
__ CallRuntime(kTypeCheckRuntimeEntry, 8);
__ Drop(2); // mode and nnbd mode
__ CallRuntime(kTypeCheckRuntimeEntry, 7);
__ Drop(1); // mode
__ Pop(kSubtypeTestCacheReg);
__ Drop(1); // dst_name
__ Pop(kFunctionTypeArgumentsReg);

View file

@ -3123,11 +3123,8 @@ static void InvokeTypeCheckFromTypeTestStub(Assembler* assembler,
__ PushObject(NullObject());
__ Push(kSubtypeTestCacheReg);
__ PushImmediate(target::ToRawSmi(mode));
// TODO(regis): Pass nnbd mode in a register from call site.
__ PushImmediate(
target::ToRawSmi(static_cast<intptr_t>(NNBDMode::kLegacyLib)));
__ CallRuntime(kTypeCheckRuntimeEntry, 8);
__ Drop(2); // mode and nnbd mode
__ CallRuntime(kTypeCheckRuntimeEntry, 7);
__ Drop(1); // mode
__ Pop(kSubtypeTestCacheReg);
__ Drop(1); // dst_name
__ Pop(kFunctionTypeArgumentsReg);

View file

@ -3078,11 +3078,8 @@ static void InvokeTypeCheckFromTypeTestStub(Assembler* assembler,
__ PushObject(NullObject());
__ pushq(kSubtypeTestCacheReg);
__ PushImmediate(Immediate(target::ToRawSmi(mode)));
// TODO(regis): Pass nnbd mode in a register from call site.
__ PushImmediate(
Immediate(target::ToRawSmi(static_cast<intptr_t>(NNBDMode::kLegacyLib))));
__ CallRuntime(kTypeCheckRuntimeEntry, 8);
__ Drop(2); // mode and nnbd_mode
__ CallRuntime(kTypeCheckRuntimeEntry, 7);
__ Drop(1); // mode
__ popq(kSubtypeTestCacheReg);
__ Drop(1);
__ popq(kFunctionTypeArgumentsReg);

View file

@ -159,9 +159,8 @@ static RawInstance* GetListInstance(Zone* zone, const Object& obj) {
}
const Instance& instance = Instance::Cast(obj);
const Class& obj_class = Class::Handle(zone, obj.clazz());
if (Class::IsSubtypeOf(NNBDMode::kLegacyLib, obj_class,
Object::null_type_arguments(), list_rare_type,
Heap::kNew)) {
if (Class::IsSubtypeOf(obj_class, Object::null_type_arguments(),
list_rare_type, Heap::kNew)) {
return instance.raw();
}
}
@ -183,9 +182,8 @@ static RawInstance* GetMapInstance(Zone* zone, const Object& obj) {
}
const Instance& instance = Instance::Cast(obj);
const Class& obj_class = Class::Handle(zone, obj.clazz());
if (Class::IsSubtypeOf(NNBDMode::kLegacyLib, obj_class,
Object::null_type_arguments(), map_rare_type,
Heap::kNew)) {
if (Class::IsSubtypeOf(obj_class, Object::null_type_arguments(),
map_rare_type, Heap::kNew)) {
return instance.raw();
}
}
@ -2188,8 +2186,7 @@ static bool InstanceIsType(const Thread* thread,
const Type& type) {
ASSERT(!type.IsNull());
CHECK_CALLBACK_STATE(thread);
return instance.IsInstanceOf(NNBDMode::kLegacyLib, type,
Object::null_type_arguments(),
return instance.IsInstanceOf(type, Object::null_type_arguments(),
Object::null_type_arguments());
}
@ -2382,9 +2379,8 @@ DART_EXPORT bool Dart_IsFuture(Dart_Handle handle) {
object_store->set_non_nullable_future_rare_type(future_rare_type);
}
const Class& obj_class = Class::Handle(Z, obj.clazz());
bool is_future = Class::IsSubtypeOf(NNBDMode::kLegacyLib, obj_class,
Object::null_type_arguments(),
future_rare_type, Heap::kNew);
bool is_future = Class::IsSubtypeOf(
obj_class, Object::null_type_arguments(), future_rare_type, Heap::kNew);
return is_future;
}
return false;
@ -4266,8 +4262,8 @@ DART_EXPORT Dart_Handle Dart_New(Dart_Handle type,
// We do not support generic constructors.
ASSERT(redirect_type.IsInstantiated(kFunctions));
redirect_type ^= redirect_type.InstantiateFrom(
NNBDMode::kLegacyLib, type_arguments, Object::null_type_arguments(),
kNoneFree, NULL, Heap::kNew);
type_arguments, Object::null_type_arguments(), kNoneFree, NULL,
Heap::kNew);
redirect_type ^= redirect_type.Canonicalize();
}

View file

@ -952,7 +952,6 @@ bool ActivationFrame::HandlesException(const Instance& exc_obj) {
handlers = code().exception_handlers();
}
ASSERT(!handlers.IsNull());
const NNBDMode nnbd_mode = function().nnbd_mode();
intptr_t num_handlers_checked = 0;
while (try_index != kInvalidTryIndex) {
// Detect circles in the exception handler data.
@ -970,7 +969,7 @@ bool ActivationFrame::HandlesException(const Instance& exc_obj) {
if (type.IsDynamicType()) {
return true;
}
if (exc_obj.IsInstanceOf(nnbd_mode, type, Object::null_type_arguments(),
if (exc_obj.IsInstanceOf(type, Object::null_type_arguments(),
Object::null_type_arguments())) {
return true;
}

View file

@ -229,22 +229,6 @@ class InterpreterHelpers {
return Class::ClassFinalizedBits::decode(cls->ptr()->state_bits_) ==
RawClass::kFinalized;
}
DART_FORCE_INLINE static RawSmi* NnbdMode(RawObject** FP) {
RawFunction* function =
static_cast<RawFunction*>(FP[kKBCFunctionSlotFromFp]);
ASSERT(function != Function::null());
RawObject* origin = function->ptr()->owner_;
if (InterpreterHelpers::GetClassId(origin) != kClassCid) {
ASSERT(InterpreterHelpers::GetClassId(origin) == kPatchClassCid);
origin = PatchClass::RawCast(origin)->ptr()->origin_class_;
}
RawLibrary* library = Class::RawCast(origin)->ptr()->library_;
return Smi::New(static_cast<intptr_t>(
RawLibrary::NnbdBit::decode(library->ptr()->flags_)
? NNBDMode::kOptedInLib
: NNBDMode::kLegacyLib));
}
};
DART_FORCE_INLINE static const KBCInstr* SavedCallerPC(RawObject** FP) {
@ -1242,14 +1226,11 @@ AssertAssignableCallRuntime:
// args[2]: Instantiator type args.
// args[3]: Function type args.
// args[4]: Name.
// args[5]: NNBD mode.
RawObject* nnbd_mode = args[5];
args[5] = cache;
args[6] = Smi::New(kTypeCheckFromInline);
args[7] = nnbd_mode;
args[8] = 0; // Unused result.
Exit(thread, FP, args + 9, pc);
NativeArguments native_args(thread, 8, args, args + 8);
args[7] = 0; // Unused result.
Exit(thread, FP, args + 8, pc);
NativeArguments native_args(thread, 7, args, args + 7);
return InvokeRuntime(thread, this, DRT_TypeCheck, native_args);
}
@ -1264,17 +1245,17 @@ bool Interpreter::AssertAssignableField(Thread* thread,
RawAbstractType* field_type = field->ptr()->type_;
// Perform type test of value if field type is not one of dynamic, object,
// or void, and if the value is not null.
// TODO(regis): Provide nnbd mode to check field and revisit top type test.
if (field_type->GetClassId() == kTypeCid) {
classid_t cid = Smi::Value(reinterpret_cast<RawSmi*>(
Type::RawCast(field_type)->ptr()->type_class_id_));
// TODO(regis): Revisit shortcut for NNBD.
if (cid == kDynamicCid || cid == kInstanceCid || cid == kVoidCid) {
return true;
}
}
RawObject* null_value = Object::null();
if (value == null_value) {
// TODO(regis): Provide nnbd mode to check field and revisit null shortcut.
// TODO(regis): Revisit null shortcut for NNBD.
return true;
}
@ -1309,8 +1290,7 @@ bool Interpreter::AssertAssignableField(Thread* thread,
SP[3] = InterpreterHelpers::GetTypeArguments(thread, instance);
SP[4] = null_value; // Implicit setters cannot be generic.
SP[5] = is_getter ? Symbols::FunctionResult().raw() : field->ptr()->name_;
SP[6] = Smi::New(static_cast<intptr_t>(NNBDMode::kLegacyLib));
return AssertAssignable(thread, pc, FP, /* call_top */ SP + 6,
return AssertAssignable(thread, pc, FP, /* call_top */ SP + 5,
/* args */ SP + 1, cache);
}
@ -1762,11 +1742,10 @@ SwitchDispatch:
SP[1] = type;
SP[2] = SP[-1];
SP[3] = SP[0];
SP[4] = InterpreterHelpers::NnbdMode(FP);
Exit(thread, FP, SP + 5, pc);
Exit(thread, FP, SP + 4, pc);
{
INVOKE_RUNTIME(DRT_InstantiateType,
NativeArguments(thread, 4, SP + 1, SP - 1));
NativeArguments(thread, 3, SP + 1, SP - 1));
}
SP -= 1;
DISPATCH();
@ -1780,7 +1759,6 @@ SwitchDispatch:
RawObject* instantiator_type_args = SP[-1];
RawObject* function_type_args = SP[0];
RawObject* nnbd_mode_as_smi = InterpreterHelpers::NnbdMode(FP);
// If both instantiators are null and if the type argument vector
// instantiated from null becomes a vector of dynamic, then use null as
// the type arguments.
@ -1798,10 +1776,7 @@ SwitchDispatch:
instantiator_type_args) &&
(instantiations->ptr()->data()
[i + TypeArguments::Instantiation::kFunctionTypeArgsIndex] ==
function_type_args) &&
(instantiations->ptr()
->data()[i + TypeArguments::Instantiation::kNnbdModeIndex] ==
nnbd_mode_as_smi)) {
function_type_args)) {
// Found in the cache.
SP[-1] =
instantiations->ptr()->data()[i + TypeArguments::Instantiation::
@ -1814,11 +1789,10 @@ SwitchDispatch:
SP[1] = type_arguments;
SP[2] = instantiator_type_args;
SP[3] = function_type_args;
SP[4] = nnbd_mode_as_smi;
Exit(thread, FP, SP + 5, pc);
Exit(thread, FP, SP + 4, pc);
INVOKE_RUNTIME(DRT_InstantiateTypeArguments,
NativeArguments(thread, 4, SP + 1, SP - 1));
NativeArguments(thread, 3, SP + 1, SP - 1));
}
InstantiateTypeArgumentsTOSDone:
@ -2637,8 +2611,7 @@ SwitchDispatch:
RawSubtypeTestCache* cache =
static_cast<RawSubtypeTestCache*>(LOAD_CONSTANT(rE));
SP[1] = InterpreterHelpers::NnbdMode(FP);
if (!AssertAssignable(thread, pc, FP, SP + 1, args, cache)) {
if (!AssertAssignable(thread, pc, FP, SP, args, cache)) {
HANDLE_EXCEPTION;
}
}
@ -2660,19 +2633,16 @@ SwitchDispatch:
// args[3] super_type
// args[4] name
SP++;
SP[0] = InterpreterHelpers::NnbdMode(FP);
// This is unused, since the negative case throws an exception.
SP++;
RawObject** result_slot = SP;
Exit(thread, FP, SP + 1, pc);
INVOKE_RUNTIME(DRT_SubtypeCheck,
NativeArguments(thread, 6, args, result_slot));
NativeArguments(thread, 5, args, result_slot));
// Drop result slot and all arguments.
SP -= 7;
SP -= 6;
DISPATCH();
}
@ -3570,8 +3540,6 @@ SwitchDispatch:
RawInstance* receiver =
Instance::RawCast(FrameArguments(FP, argc)[receiver_idx]);
SP[5] = InterpreterHelpers::GetTypeArguments(thread, receiver);
// TODO(regis): Provide correct nnbd mode.
RawSmi* nnbd_mode = Smi::New(static_cast<intptr_t>(NNBDMode::kLegacyLib));
if (type_args_len > 0) {
SP[6] = FrameArguments(FP, argc)[0];
@ -3582,10 +3550,9 @@ SwitchDispatch:
SP[7] = SP[6]; // type_arguments
SP[8] = SP[5]; // instantiator_type_args
SP[9] = null_value; // function_type_args
SP[10] = nnbd_mode;
Exit(thread, FP, SP + 11, pc);
Exit(thread, FP, SP + 10, pc);
INVOKE_RUNTIME(DRT_InstantiateTypeArguments,
NativeArguments(thread, 4, SP + 7, SP + 7));
NativeArguments(thread, 3, SP + 7, SP + 7));
SP[6] = SP[7];
}
}
@ -3605,8 +3572,7 @@ SwitchDispatch:
// SP[5]: Instantiator type args.
// SP[6]: Function type args.
SP[7] = check->ptr()->name_;
SP[8] = nnbd_mode;
if (!AssertAssignable(thread, pc, FP, SP + 8, SP + 3,
if (!AssertAssignable(thread, pc, FP, SP + 7, SP + 3,
check->ptr()->cache_)) {
HANDLE_EXCEPTION;
}
@ -3618,11 +3584,10 @@ SwitchDispatch:
SP[7] = check->ptr()->param_;
SP[8] = check->ptr()->type_or_bound_;
SP[9] = check->ptr()->name_;
SP[10] = nnbd_mode;
SP[11] = 0;
Exit(thread, FP, SP + 12, pc);
SP[10] = 0;
Exit(thread, FP, SP + 11, pc);
INVOKE_RUNTIME(DRT_SubtypeCheck,
NativeArguments(thread, 6, SP + 5, SP + 11));
NativeArguments(thread, 5, SP + 5, SP + 10));
}
checks = Array::RawCast(SP[1]); // Reload after runtime call.

View file

@ -2138,8 +2138,7 @@ class FieldInvalidator {
}
if (!cache_hit) {
const NNBDMode nnbd_mode = Class::Handle(field.Origin()).nnbd_mode();
if (!value.IsAssignableTo(nnbd_mode, type_, instantiator_type_arguments_,
if (!value.IsAssignableTo(type_, instantiator_type_arguments_,
function_type_arguments_)) {
ASSERT(!FLAG_identity_reload);
field.set_needs_load_guard(true);

View file

@ -3658,22 +3658,19 @@ RawFunction* Function::GetDynamicInvocationForwarder(
#endif
bool AbstractType::InstantiateAndTestSubtype(
NNBDMode mode,
AbstractType* subtype,
AbstractType* supertype,
const TypeArguments& instantiator_type_args,
const TypeArguments& function_type_args) {
if (!subtype->IsInstantiated()) {
*subtype = subtype->InstantiateFrom(mode, instantiator_type_args,
function_type_args, kAllFree, NULL,
Heap::kOld);
*subtype = subtype->InstantiateFrom(
instantiator_type_args, function_type_args, kAllFree, NULL, Heap::kOld);
}
if (!supertype->IsInstantiated()) {
*supertype = supertype->InstantiateFrom(mode, instantiator_type_args,
function_type_args, kAllFree, NULL,
Heap::kOld);
*supertype = supertype->InstantiateFrom(
instantiator_type_args, function_type_args, kAllFree, NULL, Heap::kOld);
}
return subtype->IsSubtypeOf(mode, *supertype, Heap::kOld);
return subtype->IsSubtypeOf(*supertype, Heap::kOld);
}
RawArray* Class::invocation_dispatcher_cache() const {
@ -3952,8 +3949,6 @@ RawObject* Class::InvokeSetter(const String& setter_name,
}
AbstractType& parameter_type = AbstractType::Handle(zone);
NNBDMode mode = nnbd_mode();
if (field.IsNull()) {
const Function& setter =
Function::Handle(zone, LookupStaticFunction(internal_setter_name));
@ -3970,7 +3965,7 @@ RawObject* Class::InvokeSetter(const String& setter_name,
InvocationMirror::kSetter);
}
parameter_type = setter.ParameterTypeAt(0);
if (!value.RuntimeTypeIsSubtypeOf(mode, parameter_type,
if (!value.RuntimeTypeIsSubtypeOf(parameter_type,
Object::null_type_arguments(),
Object::null_type_arguments())) {
const String& argument_name =
@ -3993,7 +3988,7 @@ RawObject* Class::InvokeSetter(const String& setter_name,
}
parameter_type = field.type();
if (!value.RuntimeTypeIsSubtypeOf(mode, parameter_type,
if (!value.RuntimeTypeIsSubtypeOf(parameter_type,
Object::null_type_arguments(),
Object::null_type_arguments())) {
const String& argument_name = String::Handle(zone, field.name());
@ -4053,16 +4048,14 @@ RawObject* Class::Invoke(const String& function_name,
arg_names, Heap::kNew));
ArgumentsDescriptor args_descriptor(args_descriptor_array);
const TypeArguments& type_args = Object::null_type_arguments();
if (function.IsNull() ||
!function.AreValidArguments(NNBDMode::kLegacyLib, args_descriptor,
NULL) ||
if (function.IsNull() || !function.AreValidArguments(args_descriptor, NULL) ||
(respect_reflectable && !function.is_reflectable())) {
return ThrowNoSuchMethod(
AbstractType::Handle(zone, RareType()), function_name, args, arg_names,
InvocationMirror::kStatic, InvocationMirror::kMethod);
}
RawObject* type_error = function.DoArgumentTypesMatch(
NNBDMode::kLegacyLib, args, args_descriptor, type_args);
RawObject* type_error =
function.DoArgumentTypesMatch(args, args_descriptor, type_args);
if (type_error != Error::null()) {
return type_error;
}
@ -4864,8 +4857,7 @@ bool Class::IsFutureClass() const {
// type T1 is specified by 'other' and must have a type class.
// This class and class 'other' do not need to be finalized, however, they must
// be resolved as well as their interfaces.
bool Class::IsSubtypeOf(NNBDMode mode,
const Class& cls,
bool Class::IsSubtypeOf(const Class& cls,
const TypeArguments& type_arguments,
const AbstractType& other,
Heap::Space space) {
@ -4903,12 +4895,11 @@ bool Class::IsSubtypeOf(NNBDMode mode,
ASSERT(!future_class.IsNull() && future_class.NumTypeParameters() == 1 &&
this_class.NumTypeParameters() == 1);
ASSERT(type_arguments.IsNull() || type_arguments.Length() >= 1);
if (Class::IsSubtypeOf(mode, future_class, type_arguments, other,
space)) {
if (Class::IsSubtypeOf(future_class, type_arguments, other, space)) {
// Check S0 <: T1.
const AbstractType& type_arg =
AbstractType::Handle(zone, type_arguments.TypeAtNullSafe(0));
if (type_arg.IsSubtypeOf(mode, other, space)) {
if (type_arg.IsSubtypeOf(other, space)) {
return true;
}
}
@ -4932,14 +4923,14 @@ bool Class::IsSubtypeOf(NNBDMode mode,
const AbstractType& type_arg =
AbstractType::Handle(zone, type_arguments.TypeAtNullSafe(0));
// If T0 is Future<S0>, then T0 <: Future<S1>, iff S0 <: S1.
if (type_arg.IsSubtypeOf(mode, other_type_arg, space)) {
if (type_arg.IsSubtypeOf(other_type_arg, space)) {
return true;
}
}
// Check T0 <: Future<S1> when T0 is FutureOr<S0> is already done.
// Check T0 <: S1.
if (other_type_arg.HasTypeClass() &&
Class::IsSubtypeOf(mode, this_class, type_arguments, other_type_arg,
Class::IsSubtypeOf(this_class, type_arguments, other_type_arg,
space)) {
return true;
}
@ -4967,7 +4958,7 @@ bool Class::IsSubtypeOf(NNBDMode mode,
// above.
return false;
}
return type_arguments.IsSubtypeOf(mode, other_type_arguments, from_index,
return type_arguments.IsSubtypeOf(other_type_arguments, from_index,
num_type_params, space);
}
// Check for 'direct super type' specified in the implements clause
@ -4991,16 +4982,15 @@ bool Class::IsSubtypeOf(NNBDMode mode,
// after the type arguments of the super type of this type.
// The index of the type parameters is adjusted upon finalization.
interface_args = interface_args.InstantiateFrom(
this_class.nnbd_mode(), type_arguments,
Object::null_type_arguments(), kNoneFree, NULL, space);
type_arguments, Object::null_type_arguments(), kNoneFree, NULL,
space);
}
// In Dart 2, implementing Function has no meaning.
// TODO(regis): Can we encounter and skip Object as well?
if (interface_class.IsDartFunctionClass()) {
continue;
}
if (Class::IsSubtypeOf(mode, interface_class, interface_args, other,
space)) {
if (Class::IsSubtypeOf(interface_class, interface_args, other, space)) {
return true;
}
}
@ -5763,8 +5753,7 @@ bool TypeArguments::IsTopTypes(intptr_t from_index, intptr_t len) const {
return true;
}
bool TypeArguments::IsSubtypeOf(NNBDMode mode,
const TypeArguments& other,
bool TypeArguments::IsSubtypeOf(const TypeArguments& other,
intptr_t from_index,
intptr_t len,
Heap::Space space) const {
@ -5777,7 +5766,7 @@ bool TypeArguments::IsSubtypeOf(NNBDMode mode,
type = TypeAt(from_index + i);
other_type = other.TypeAt(from_index + i);
if (type.IsNull() || other_type.IsNull() ||
!type.IsSubtypeOf(mode, other_type, space)) {
!type.IsSubtypeOf(other_type, space)) {
return false;
}
}
@ -6003,7 +5992,6 @@ bool TypeArguments::IsFinalized() const {
}
RawTypeArguments* TypeArguments::InstantiateFrom(
NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
@ -6030,7 +6018,7 @@ RawTypeArguments* TypeArguments::InstantiateFrom(
if (!type.IsNull() &&
!type.IsInstantiated(kAny, num_free_fun_type_params)) {
type = type.InstantiateFrom(
mode, instantiator_type_arguments, function_type_arguments,
instantiator_type_arguments, function_type_arguments,
num_free_fun_type_params, instantiation_trail, space);
// A returned null type indicates a failed instantiation in dead code that
// must be propagated up to the caller, the optimizing compiler.
@ -6044,7 +6032,6 @@ RawTypeArguments* TypeArguments::InstantiateFrom(
}
RawTypeArguments* TypeArguments::InstantiateAndCanonicalizeFrom(
NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments) const {
ASSERT(!IsInstantiated());
@ -6052,9 +6039,7 @@ RawTypeArguments* TypeArguments::InstantiateAndCanonicalizeFrom(
instantiator_type_arguments.IsCanonical());
ASSERT(function_type_arguments.IsNull() ||
function_type_arguments.IsCanonical());
const Smi& nnbd_mode_as_smi =
Smi::Handle(Smi::New(static_cast<intptr_t>(mode)));
// Lookup instantiators and mode, and if found, return instantiated result.
// Lookup instantiators and if found, return instantiated result.
Array& prior_instantiations = Array::Handle(instantiations());
ASSERT(!prior_instantiations.IsNull() && prior_instantiations.IsArray());
// The instantiations cache is initialized with Object::zero_array() and is
@ -6068,10 +6053,7 @@ RawTypeArguments* TypeArguments::InstantiateAndCanonicalizeFrom(
instantiator_type_arguments.raw()) &&
(prior_instantiations.At(
index + TypeArguments::Instantiation::kFunctionTypeArgsIndex) ==
function_type_arguments.raw()) &&
(prior_instantiations.At(
index + TypeArguments::Instantiation::kNnbdModeIndex) ==
nnbd_mode_as_smi.raw())) {
function_type_arguments.raw())) {
return TypeArguments::RawCast(prior_instantiations.At(
index + TypeArguments::Instantiation::kInstantiatedTypeArgsIndex));
}
@ -6083,8 +6065,8 @@ RawTypeArguments* TypeArguments::InstantiateAndCanonicalizeFrom(
}
// Cache lookup failed. Instantiate the type arguments.
TypeArguments& result = TypeArguments::Handle();
result = InstantiateFrom(mode, instantiator_type_arguments,
function_type_arguments, kAllFree, NULL, Heap::kOld);
result = InstantiateFrom(instantiator_type_arguments, function_type_arguments,
kAllFree, NULL, Heap::kOld);
// Canonicalize type arguments.
result = result.Canonicalize();
// InstantiateAndCanonicalizeFrom is not reentrant. It cannot have been called
@ -6111,8 +6093,6 @@ RawTypeArguments* TypeArguments::InstantiateAndCanonicalizeFrom(
prior_instantiations.SetAt(
index + TypeArguments::Instantiation::kFunctionTypeArgsIndex,
function_type_arguments);
prior_instantiations.SetAt(
index + TypeArguments::Instantiation::kNnbdModeIndex, nnbd_mode_as_smi);
prior_instantiations.SetAt(
index + TypeArguments::Instantiation::kInstantiatedTypeArgsIndex, result);
prior_instantiations.SetAt(
@ -7421,19 +7401,17 @@ bool Function::AreValidArgumentCounts(intptr_t num_type_arguments,
return true;
}
bool Function::AreValidArguments(NNBDMode mode,
intptr_t num_type_arguments,
bool Function::AreValidArguments(intptr_t num_type_arguments,
intptr_t num_arguments,
const Array& argument_names,
String* error_message) const {
const Array& args_desc_array = Array::Handle(ArgumentsDescriptor::New(
num_type_arguments, num_arguments, argument_names, Heap::kNew));
ArgumentsDescriptor args_desc(args_desc_array);
return AreValidArguments(mode, args_desc, error_message);
return AreValidArguments(args_desc, error_message);
}
bool Function::AreValidArguments(NNBDMode mode,
const ArgumentsDescriptor& args_desc,
bool Function::AreValidArguments(const ArgumentsDescriptor& args_desc,
String* error_message) const {
const intptr_t num_type_arguments = args_desc.TypeArgsLen();
const intptr_t num_arguments = args_desc.Count();
@ -7506,7 +7484,6 @@ bool Function::AreValidArguments(NNBDMode mode,
}
RawObject* Function::DoArgumentTypesMatch(
NNBDMode mode,
const Array& args,
const ArgumentsDescriptor& args_desc,
const TypeArguments& instantiator_type_args) const {
@ -7515,7 +7492,7 @@ RawObject* Function::DoArgumentTypesMatch(
Function& instantiated_func = Function::Handle(zone, raw());
if (!HasInstantiatedSignature()) {
instantiated_func = InstantiateSignatureFrom(mode, instantiator_type_args,
instantiated_func = InstantiateSignatureFrom(instantiator_type_args,
Object::null_type_arguments(),
kAllFree, Heap::kNew);
}
@ -7534,7 +7511,7 @@ RawObject* Function::DoArgumentTypesMatch(
if (parameter_type.IsDynamicType() || argument_type.IsNullType()) {
continue;
}
if (!argument.IsInstanceOf(mode, parameter_type, instantiator_type_args,
if (!argument.IsInstanceOf(parameter_type, instantiator_type_args,
Object::null_type_arguments())) {
String& argument_name = String::Handle(zone, ParameterNameAt(i));
return ThrowTypeError(token_pos(), argument, parameter_type,
@ -7574,7 +7551,7 @@ RawObject* Function::DoArgumentTypesMatch(
if (parameter_type.IsDynamicType() || argument_type.IsNullType()) {
continue;
}
if (!argument.IsInstanceOf(mode, parameter_type, instantiator_type_args,
if (!argument.IsInstanceOf(parameter_type, instantiator_type_args,
Object::null_type_arguments())) {
String& argument_name = String::Handle(zone, ParameterNameAt(i));
return ThrowTypeError(token_pos(), argument, parameter_type,
@ -7680,7 +7657,6 @@ const char* Function::ToQualifiedCString() const {
}
RawFunction* Function::InstantiateSignatureFrom(
NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
@ -7733,7 +7709,7 @@ RawFunction* Function::InstantiateSignatureFrom(
type_param ^= type_params.TypeAt(i);
type = type_param.bound();
if (!type.IsInstantiated(kAny, num_free_fun_type_params)) {
type = type.InstantiateFrom(mode, instantiator_type_arguments,
type = type.InstantiateFrom(instantiator_type_arguments,
function_type_arguments,
num_free_fun_type_params, NULL, space);
// A returned null type indicates a failed instantiation in dead code
@ -7769,7 +7745,7 @@ RawFunction* Function::InstantiateSignatureFrom(
type = result_type();
if (!type.IsInstantiated(kAny, num_free_fun_type_params)) {
type = type.InstantiateFrom(mode, instantiator_type_arguments,
type = type.InstantiateFrom(instantiator_type_arguments,
function_type_arguments,
num_free_fun_type_params, NULL, space);
// A returned null type indicates a failed instantiation in dead code that
@ -7787,7 +7763,7 @@ RawFunction* Function::InstantiateSignatureFrom(
for (intptr_t i = 0; i < num_params; i++) {
type = ParameterTypeAt(i);
if (!type.IsInstantiated(kAny, num_free_fun_type_params)) {
type = type.InstantiateFrom(mode, instantiator_type_arguments,
type = type.InstantiateFrom(instantiator_type_arguments,
function_type_arguments,
num_free_fun_type_params, NULL, space);
// A returned null type indicates a failed instantiation in dead code that
@ -7810,8 +7786,7 @@ RawFunction* Function::InstantiateSignatureFrom(
// of the type of the specified parameter of the other function (i.e. check
// parameter contravariance).
// Note that types marked as covariant are already dealt with in the front-end.
bool Function::IsContravariantParameter(NNBDMode mode,
intptr_t parameter_position,
bool Function::IsContravariantParameter(intptr_t parameter_position,
const Function& other,
intptr_t other_parameter_position,
Heap::Space space) const {
@ -7822,7 +7797,7 @@ bool Function::IsContravariantParameter(NNBDMode mode,
}
const AbstractType& other_param_type =
AbstractType::Handle(other.ParameterTypeAt(other_parameter_position));
return other_param_type.IsSubtypeOf(mode, param_type, space);
return other_param_type.IsSubtypeOf(param_type, space);
}
bool Function::HasSameTypeParametersAndBounds(const Function& other,
@ -7835,7 +7810,6 @@ bool Function::HasSameTypeParametersAndBounds(const Function& other,
return false;
}
if (num_type_params > 0) {
const NNBDMode mode = nnbd_mode(); // TODO(regis): Remove unused mode.
const TypeArguments& type_params =
TypeArguments::Handle(zone, type_parameters());
ASSERT(!type_params.IsNull());
@ -7855,8 +7829,8 @@ bool Function::HasSameTypeParametersAndBounds(const Function& other,
ASSERT(other_bound.IsFinalized());
if (Dart::non_nullable_flag() && kind == TypeEquality::kInSubtypeTest) {
// Bounds that are mutual subtypes are considered equal.
if (!bound.IsSubtypeOf(mode, other_bound, Heap::kOld) ||
!other_bound.IsSubtypeOf(mode, bound, Heap::kOld)) {
if (!bound.IsSubtypeOf(other_bound, Heap::kOld) ||
!other_bound.IsSubtypeOf(bound, Heap::kOld)) {
return false;
}
} else {
@ -7869,9 +7843,7 @@ bool Function::HasSameTypeParametersAndBounds(const Function& other,
return true;
}
bool Function::IsSubtypeOf(NNBDMode mode,
const Function& other,
Heap::Space space) const {
bool Function::IsSubtypeOf(const Function& other, Heap::Space space) const {
const intptr_t num_fixed_params = num_fixed_parameters();
const intptr_t num_opt_pos_params = NumOptionalPositionalParameters();
const intptr_t num_opt_named_params = NumOptionalNamedParameters();
@ -7904,7 +7876,7 @@ bool Function::IsSubtypeOf(NNBDMode 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(mode, other_res_type, space)) {
if (!res_type.IsSubtypeOf(other_res_type, space)) {
return false;
}
}
@ -7912,7 +7884,7 @@ bool Function::IsSubtypeOf(NNBDMode mode,
for (intptr_t i = 0; i < (other_num_fixed_params - other_num_ignored_params +
other_num_opt_pos_params);
i++) {
if (!IsContravariantParameter(mode, i + num_ignored_params, other,
if (!IsContravariantParameter(i + num_ignored_params, other,
i + other_num_ignored_params, space)) {
return false;
}
@ -7940,7 +7912,7 @@ bool Function::IsSubtypeOf(NNBDMode mode,
ASSERT(String::Handle(zone, ParameterNameAt(j)).IsSymbol());
if (ParameterNameAt(j) == other_param_name.raw()) {
found_param_name = true;
if (!IsContravariantParameter(mode, j, other, i, space)) {
if (!IsContravariantParameter(j, other, i, space)) {
return false;
}
if (FLAG_null_safety && IsRequiredAt(j) && !other_is_required) {
@ -10044,8 +10016,8 @@ StaticTypeExactnessState StaticTypeExactnessState::Compute(
for (intptr_t i = path.length() - 2; (i >= 0) && !type.IsInstantiated();
i--) {
args = path[i]->arguments();
type = type.InstantiateFrom(NNBDMode::kLegacyLib, args,
TypeArguments::null_type_arguments(), kAllFree,
type = type.InstantiateFrom(args, TypeArguments::null_type_arguments(),
kAllFree,
/*instantiation_trail=*/nullptr, Heap::kNew);
}
@ -11980,15 +11952,13 @@ static RawObject* InvokeInstanceFunction(
// Note "args" is already the internal arguments with the receiver as the
// first element.
ArgumentsDescriptor args_descriptor(args_descriptor_array);
if (function.IsNull() ||
!function.AreValidArguments(NNBDMode::kLegacyLib, args_descriptor,
NULL) ||
if (function.IsNull() || !function.AreValidArguments(args_descriptor, NULL) ||
(respect_reflectable && !function.is_reflectable())) {
return DartEntry::InvokeNoSuchMethod(receiver, target_name, args,
args_descriptor_array);
}
RawObject* type_error = function.DoArgumentTypesMatch(
NNBDMode::kLegacyLib, args, args_descriptor, instantiator_type_args);
RawObject* type_error = function.DoArgumentTypesMatch(args, args_descriptor,
instantiator_type_args);
if (type_error != Error::null()) {
return type_error;
}
@ -12079,8 +12049,7 @@ RawObject* Library::InvokeSetter(const String& setter_name,
}
setter_type = field.type();
if (!argument_type.IsNullType() && !setter_type.IsDynamicType() &&
!value.IsInstanceOf(nnbd_mode(), setter_type,
Object::null_type_arguments(),
!value.IsInstanceOf(setter_type, Object::null_type_arguments(),
Object::null_type_arguments())) {
return ThrowTypeError(field.token_pos(), value, setter_type, setter_name);
}
@ -12120,8 +12089,7 @@ RawObject* Library::InvokeSetter(const String& setter_name,
setter_type = setter.ParameterTypeAt(0);
if (!argument_type.IsNullType() && !setter_type.IsDynamicType() &&
!value.IsInstanceOf(nnbd_mode(), setter_type,
Object::null_type_arguments(),
!value.IsInstanceOf(setter_type, Object::null_type_arguments(),
Object::null_type_arguments())) {
return ThrowTypeError(setter.token_pos(), value, setter_type, setter_name);
}
@ -12176,17 +12144,15 @@ RawObject* Library::Invoke(const String& function_name,
kTypeArgsLen, args.Length(), arg_names, Heap::kNew));
ArgumentsDescriptor args_descriptor(args_descriptor_array);
const TypeArguments& type_args = Object::null_type_arguments();
if (function.IsNull() ||
!function.AreValidArguments(NNBDMode::kLegacyLib, args_descriptor,
NULL) ||
if (function.IsNull() || !function.AreValidArguments(args_descriptor, NULL) ||
(respect_reflectable && !function.is_reflectable())) {
return ThrowNoSuchMethod(
AbstractType::Handle(Class::Handle(toplevel_class()).RareType()),
function_name, args, arg_names, InvocationMirror::kTopLevel,
InvocationMirror::kMethod);
}
RawObject* type_error = function.DoArgumentTypesMatch(
NNBDMode::kLegacyLib, args, args_descriptor, type_args);
RawObject* type_error =
function.DoArgumentTypesMatch(args, args_descriptor, type_args);
if (type_error != Error::null()) {
return type_error;
}
@ -17548,24 +17514,21 @@ Casts (e as T) in strong checking mode in a legacy or opted-in library:
*/
bool Instance::IsInstanceOf(
NNBDMode mode,
const AbstractType& other,
const TypeArguments& other_instantiator_type_arguments,
const TypeArguments& other_function_type_arguments) const {
ASSERT(!other.IsDynamicType());
if (IsNull()) {
return Instance::NullIsInstanceOf(mode, other,
other_instantiator_type_arguments,
return Instance::NullIsInstanceOf(other, other_instantiator_type_arguments,
other_function_type_arguments);
}
// In strong mode, compute NNBD_SUBTYPE(runtimeType, other).
// In weak mode, compute LEGACY_SUBTYPE(runtimeType, other).
return RuntimeTypeIsSubtypeOf(mode, other, other_instantiator_type_arguments,
return RuntimeTypeIsSubtypeOf(other, other_instantiator_type_arguments,
other_function_type_arguments);
}
bool Instance::IsAssignableTo(
NNBDMode mode,
const AbstractType& other,
const TypeArguments& other_instantiator_type_arguments,
const TypeArguments& other_function_type_arguments) const {
@ -17576,17 +17539,15 @@ bool Instance::IsAssignableTo(
ASSERT(FLAG_null_safety || !IsNull());
// In strong mode, compute NNBD_SUBTYPE(runtimeType, other).
// In weak mode, compute LEGACY_SUBTYPE(runtimeType, other).
return RuntimeTypeIsSubtypeOf(mode, other, other_instantiator_type_arguments,
return RuntimeTypeIsSubtypeOf(other, other_instantiator_type_arguments,
other_function_type_arguments);
}
// If 'other' type (once instantiated) is a legacy type:
// return LEGACY_SUBTYPE(other, Null) || LEGACY_SUBTYPE(Object, other).
// Otherwise return NNBD_SUBTYPE(Null, T).
// Use 'mode' to instantiate 'other'. TODO(regis): Remove unused mode.
// Ignore value of strong flag value.
bool Instance::NullIsInstanceOf(
NNBDMode mode,
const AbstractType& other,
const TypeArguments& other_instantiator_type_arguments,
const TypeArguments& other_function_type_arguments) {
@ -17598,19 +17559,19 @@ bool Instance::NullIsInstanceOf(
}
if (other.IsFutureOrType()) {
const auto& type = AbstractType::Handle(other.UnwrapFutureOr());
return NullIsInstanceOf(mode, type, other_instantiator_type_arguments,
return NullIsInstanceOf(type, other_instantiator_type_arguments,
other_function_type_arguments);
}
// No need to instantiate type, unless it is a type parameter.
// Note that a typeref cannot refer to a type parameter.
if (other.IsTypeParameter()) {
auto& type = AbstractType::Handle(other.InstantiateFrom(
mode, other_instantiator_type_arguments, other_function_type_arguments,
other_instantiator_type_arguments, other_function_type_arguments,
kAllFree, NULL, Heap::kOld));
if (type.IsTypeRef()) {
type = TypeRef::Cast(type).type();
}
return Instance::NullIsInstanceOf(mode, type, Object::null_type_arguments(),
return Instance::NullIsInstanceOf(type, Object::null_type_arguments(),
Object::null_type_arguments());
}
return other.IsLegacy() && (other.IsTopType() || other.IsNeverType());
@ -17634,7 +17595,6 @@ bool Instance::NullIsAssignableTo(const AbstractType& other) {
}
bool Instance::RuntimeTypeIsSubtypeOf(
NNBDMode mode,
const AbstractType& other,
const TypeArguments& other_instantiator_type_arguments,
const TypeArguments& other_function_type_arguments) const {
@ -17660,8 +17620,8 @@ bool Instance::RuntimeTypeIsSubtypeOf(
AbstractType& instantiated_other = AbstractType::Handle(zone, other.raw());
if (!other.IsInstantiated()) {
instantiated_other = other.InstantiateFrom(
mode, other_instantiator_type_arguments,
other_function_type_arguments, kAllFree, NULL, Heap::kOld);
other_instantiator_type_arguments, other_function_type_arguments,
kAllFree, NULL, Heap::kOld);
if (instantiated_other.IsTypeRef()) {
instantiated_other = TypeRef::Cast(instantiated_other).type();
}
@ -17670,7 +17630,7 @@ bool Instance::RuntimeTypeIsSubtypeOf(
return true;
}
}
if (IsFutureOrInstanceOf(zone, mode, instantiated_other)) {
if (IsFutureOrInstanceOf(zone, instantiated_other)) {
return true;
}
if (!instantiated_other.IsFunctionType()) {
@ -17680,7 +17640,7 @@ bool Instance::RuntimeTypeIsSubtypeOf(
Function::Handle(zone, Type::Cast(instantiated_other).signature());
const Function& sig_fun =
Function::Handle(Closure::Cast(*this).GetInstantiatedSignature(zone));
return sig_fun.IsSubtypeOf(mode, other_signature, Heap::kOld);
return sig_fun.IsSubtypeOf(other_signature, Heap::kOld);
}
TypeArguments& type_arguments = TypeArguments::Handle(zone);
if (cls.NumTypeArguments() > 0) {
@ -17700,7 +17660,7 @@ bool Instance::RuntimeTypeIsSubtypeOf(
AbstractType& instantiated_other = AbstractType::Handle(zone, other.raw());
if (!other.IsInstantiated()) {
instantiated_other = other.InstantiateFrom(
mode, other_instantiator_type_arguments, other_function_type_arguments,
other_instantiator_type_arguments, other_function_type_arguments,
kAllFree, NULL, Heap::kOld);
if (instantiated_other.IsTypeRef()) {
instantiated_other = TypeRef::Cast(instantiated_other).type();
@ -17717,19 +17677,18 @@ bool Instance::RuntimeTypeIsSubtypeOf(
if (instantiated_other.IsNullType()) {
return true;
}
if (IsFutureOrInstanceOf(zone, mode, instantiated_other)) {
if (IsFutureOrInstanceOf(zone, instantiated_other)) {
return true;
}
return !instantiated_other.IsNonNullable();
}
// RuntimeType of non-null instance is non-nullable, so there is no need to
// check nullability of other type.
return Class::IsSubtypeOf(mode, cls, type_arguments, instantiated_other,
return Class::IsSubtypeOf(cls, type_arguments, instantiated_other,
Heap::kOld);
}
bool Instance::IsFutureOrInstanceOf(Zone* zone,
NNBDMode mode,
const AbstractType& other) const {
if (other.IsFutureOrType()) {
const TypeArguments& other_type_arguments =
@ -17744,13 +17703,12 @@ bool Instance::IsFutureOrInstanceOf(Zone* zone,
TypeArguments::Handle(zone, GetTypeArguments());
const AbstractType& type_arg =
AbstractType::Handle(zone, type_arguments.TypeAtNullSafe(0));
if (type_arg.IsSubtypeOf(mode, other_type_arg, Heap::kOld)) {
if (type_arg.IsSubtypeOf(other_type_arg, Heap::kOld)) {
return true;
}
}
// Retry RuntimeTypeIsSubtypeOf after unwrapping type arg of FutureOr.
if (RuntimeTypeIsSubtypeOf(mode, other_type_arg,
Object::null_type_arguments(),
if (RuntimeTypeIsSubtypeOf(other_type_arg, Object::null_type_arguments(),
Object::null_type_arguments())) {
return true;
}
@ -17981,11 +17939,10 @@ RawAbstractType* AbstractType::SetInstantiatedNullability(
const Nullability arg_nullability = nullability();
const Nullability var_nullability = type_param.nullability();
// Adjust nullability of result 'arg' instantiated from 'var'.
// arg/var ! ? * %
// ! ! ? * !
// ? ? ? ? ?
// * * ? * *
// % % ? * %
// arg/var ! ? *
// ! ! ? *
// ? ? ? ?
// * * ? *
if (var_nullability == Nullability::kNullable ||
arg_nullability == Nullability::kNullable) {
result_nullability = Nullability::kNullable;
@ -18106,7 +18063,6 @@ bool AbstractType::IsRecursive() const {
}
RawAbstractType* AbstractType::InstantiateFrom(
NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
@ -18481,8 +18437,7 @@ RawAbstractType* AbstractType::UnwrapFutureOr() const {
return type_arg.raw();
}
bool AbstractType::IsSubtypeOf(NNBDMode mode,
const AbstractType& other,
bool AbstractType::IsSubtypeOf(const AbstractType& other,
Heap::Space space) const {
ASSERT(IsFinalized());
ASSERT(other.IsFinalized());
@ -18536,11 +18491,11 @@ bool AbstractType::IsSubtypeOf(NNBDMode mode,
}
const AbstractType& bound = AbstractType::Handle(zone, type_param.bound());
ASSERT(bound.IsFinalized());
if (bound.IsSubtypeOf(mode, other, space)) {
if (bound.IsSubtypeOf(other, space)) {
return true;
}
// Apply additional subtyping rules if 'other' is 'FutureOr'.
if (IsSubtypeOfFutureOr(zone, mode, other, space)) {
if (IsSubtypeOfFutureOr(zone, other, space)) {
return true;
}
return false;
@ -18565,7 +18520,7 @@ bool AbstractType::IsSubtypeOf(NNBDMode mode,
// Check for two function types.
const Function& fun =
Function::Handle(zone, Type::Cast(*this).signature());
return fun.IsSubtypeOf(mode, other_fun, space);
return fun.IsSubtypeOf(other_fun, space);
}
if (other.IsFunctionType() && !other_type_cls.IsTypedefClass()) {
// [this] is not a function type. Therefore, non-function type [this]
@ -18582,17 +18537,16 @@ bool AbstractType::IsSubtypeOf(NNBDMode mode,
}
if (IsFunctionType()) {
// Apply additional subtyping rules if 'other' is 'FutureOr'.
if (IsSubtypeOfFutureOr(zone, mode, other, space)) {
if (IsSubtypeOfFutureOr(zone, other, space)) {
return true;
}
return false;
}
return Class::IsSubtypeOf(
mode, type_cls, TypeArguments::Handle(zone, arguments()), other, space);
return Class::IsSubtypeOf(type_cls, TypeArguments::Handle(zone, arguments()),
other, space);
}
bool AbstractType::IsSubtypeOfFutureOr(Zone* zone,
NNBDMode mode,
const AbstractType& other,
Heap::Space space) const {
if (other.IsFutureOrType()) {
@ -18608,7 +18562,7 @@ bool AbstractType::IsSubtypeOfFutureOr(Zone* zone,
return true;
}
// Retry the IsSubtypeOf check after unwrapping type arg of FutureOr.
if (IsSubtypeOf(mode, other_type_arg, space)) {
if (IsSubtypeOf(other_type_arg, space)) {
return true;
}
}
@ -18858,7 +18812,6 @@ bool Type::IsInstantiated(Genericity genericity,
}
RawAbstractType* Type::InstantiateFrom(
NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
@ -18881,7 +18834,7 @@ RawAbstractType* Type::InstantiateFrom(
// parameterization of a generic typedef. They are otherwise ignored.
ASSERT(type_arguments.Length() == cls.NumTypeArguments());
type_arguments = type_arguments.InstantiateFrom(
mode, instantiator_type_arguments, function_type_arguments,
instantiator_type_arguments, function_type_arguments,
num_free_fun_type_params, instantiation_trail, space);
// A returned empty_type_arguments indicates a failed instantiation in dead
// code that must be propagated up to the caller, the optimizing compiler.
@ -18903,7 +18856,7 @@ RawAbstractType* Type::InstantiateFrom(
// A generic typedef may actually declare an instantiated signature.
if (!sig_fun.HasInstantiatedSignature(kAny, num_free_fun_type_params)) {
sig_fun = sig_fun.InstantiateSignatureFrom(
mode, instantiator_type_arguments, function_type_arguments,
instantiator_type_arguments, function_type_arguments,
num_free_fun_type_params, space);
// A returned null signature indicates a failed instantiation in dead
// code that must be propagated up to the caller, the optimizing
@ -19481,7 +19434,6 @@ bool TypeRef::IsEquivalent(const Instance& other,
}
RawTypeRef* TypeRef::InstantiateFrom(
NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
@ -19499,7 +19451,7 @@ RawTypeRef* TypeRef::InstantiateFrom(
ASSERT(!ref_type.IsNull() && !ref_type.IsTypeRef());
AbstractType& instantiated_ref_type = AbstractType::Handle();
instantiated_ref_type = ref_type.InstantiateFrom(
mode, instantiator_type_arguments, function_type_arguments,
instantiator_type_arguments, function_type_arguments,
num_free_fun_type_params, instantiation_trail, space);
// A returned null type indicates a failed instantiation in dead code that
// must be propagated up to the caller, the optimizing compiler.
@ -19774,7 +19726,6 @@ RawAbstractType* TypeParameter::GetFromTypeArguments(
}
RawAbstractType* TypeParameter::InstantiateFrom(
NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
@ -23110,9 +23061,8 @@ RawFunction* Closure::GetInstantiatedSignature(Zone* zone) const {
}
if (num_free_params == kCurrentAndEnclosingFree ||
!sig_fun.HasInstantiatedSignature(kAny)) {
return sig_fun.InstantiateSignatureFrom(sig_fun.nnbd_mode(), inst_type_args,
fn_type_args, num_free_params,
Heap::kOld);
return sig_fun.InstantiateSignatureFrom(inst_type_args, fn_type_args,
num_free_params, Heap::kOld);
}
return sig_fun.raw();
}

View file

@ -886,9 +886,7 @@ enum class TypeEquality {
kInSubtypeTest = 2,
};
// The NNBDMode is passed to routines performing type reification and/or subtype
// tests. The mode reflects the opted-in status of the library performing type
// reification and/or subtype tests.
// The NNBDMode reflects the opted-in status of libraries.
// Note that the weak or strong testing mode is not reflected in NNBDMode, but
// imposed globally by the value of FLAG_null_safety.
enum class NNBDMode {
@ -1022,7 +1020,7 @@ class Class : public Object {
// to this class.
RawClass* Mixin() const;
// The NNBD mode to use when compiling type tests.
// The NNBD mode of the library declaring this class.
NNBDMode nnbd_mode() const;
bool IsInFullSnapshot() const;
@ -1234,8 +1232,7 @@ class Class : public Object {
// Returns true if the type specified by cls and type_arguments is a subtype
// of the other type.
static bool IsSubtypeOf(NNBDMode mode,
const Class& cls,
static bool IsSubtypeOf(const Class& cls,
const TypeArguments& type_arguments,
const AbstractType& other,
Heap::Space space);
@ -2453,7 +2450,6 @@ class Function : public Object {
// Return a new function with instantiated result and parameter types.
RawFunction* InstantiateSignatureFrom(
NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
@ -2490,7 +2486,7 @@ class Function : public Object {
RawScript* script() const;
RawObject* RawOwner() const { return raw_ptr()->owner_; }
// The NNBD mode to use when compiling type tests.
// The NNBD mode of the library declaring this function.
// TODO(alexmarkov): nnbd_mode() doesn't work for mixins.
// It should be either removed or fixed.
NNBDMode nnbd_mode() const { return Class::Handle(origin()).nnbd_mode(); }
@ -3054,7 +3050,6 @@ class Function : public Object {
// Returns a TypeError if the provided arguments don't match the function
// parameter types, NULL otherwise. Assumes AreValidArguments is called first.
RawObject* DoArgumentTypesMatch(
NNBDMode mode,
const Array& args,
const ArgumentsDescriptor& arg_names,
const TypeArguments& instantiator_type_args) const;
@ -3062,13 +3057,11 @@ class Function : public Object {
// Returns true if the type argument count, total argument count and the names
// of optional arguments are valid for calling this function.
// Otherwise, it returns false and the reason (if error_message is not NULL).
bool AreValidArguments(NNBDMode mode,
intptr_t num_type_arguments,
bool AreValidArguments(intptr_t num_type_arguments,
intptr_t num_arguments,
const Array& argument_names,
String* error_message) const;
bool AreValidArguments(NNBDMode mode,
const ArgumentsDescriptor& args_desc,
bool AreValidArguments(const ArgumentsDescriptor& args_desc,
String* error_message) const;
// Fully qualified name uniquely identifying the function under gdb and during
@ -3081,9 +3074,7 @@ class Function : public Object {
// Returns true if the type of this function is a subtype of the type of
// the other function.
bool IsSubtypeOf(NNBDMode mode,
const Function& other,
Heap::Space space) const;
bool IsSubtypeOf(const Function& other, Heap::Space space) const;
bool IsDispatcherOrImplicitAccessor() const {
switch (kind()) {
@ -3524,8 +3515,7 @@ class Function : public Object {
// Returns true if the type of the formal parameter at the given position in
// this function is contravariant with the type of the other formal parameter
// at the given position in the other function.
bool IsContravariantParameter(NNBDMode mode,
intptr_t parameter_position,
bool IsContravariantParameter(intptr_t parameter_position,
const Function& other,
intptr_t other_parameter_position,
Heap::Space space) const;
@ -6860,15 +6850,13 @@ class Instance : public Object {
// Check if the type of this instance is a subtype of the given other type.
// The type argument vectors are used to instantiate the other type if needed.
bool IsInstanceOf(NNBDMode mode,
const AbstractType& other,
bool IsInstanceOf(const AbstractType& other,
const TypeArguments& other_instantiator_type_arguments,
const TypeArguments& other_function_type_arguments) const;
// Check if this instance is assignable to the given other type.
// The type argument vectors are used to instantiate the other type if needed.
bool IsAssignableTo(NNBDMode mode,
const AbstractType& other,
bool IsAssignableTo(const AbstractType& other,
const TypeArguments& other_instantiator_type_arguments,
const TypeArguments& other_function_type_arguments) const;
@ -6881,7 +6869,6 @@ class Instance : public Object {
// specified by instantiated type 'other'.
// Returns false if other type is not a FutureOr.
bool IsFutureOrInstanceOf(Zone* zone,
NNBDMode mode,
const AbstractType& other) const;
bool IsValidNativeIndex(int index) const {
@ -6962,14 +6949,12 @@ class Instance : public Object {
private:
// Return true if the runtimeType of this instance is a subtype of other type.
bool RuntimeTypeIsSubtypeOf(
NNBDMode mode,
const AbstractType& other,
const TypeArguments& other_instantiator_type_arguments,
const TypeArguments& other_function_type_arguments) const;
// Return true if the null instance is an instance of other type.
static bool NullIsInstanceOf(
NNBDMode mode,
const AbstractType& other,
const TypeArguments& other_instantiator_type_arguments,
const TypeArguments& other_function_type_arguments);
@ -7132,8 +7117,7 @@ class TypeArguments : public Instance {
// Check the subtype relationship, considering only a subvector of length
// 'len' starting at 'from_index'.
bool IsSubtypeOf(NNBDMode mode,
const TypeArguments& other,
bool IsSubtypeOf(const TypeArguments& other,
intptr_t from_index,
intptr_t len,
Heap::Space space) const;
@ -7196,7 +7180,6 @@ class TypeArguments : public Instance {
// type from the various type argument vectors (class instantiator, function,
// or parent functions via the current context).
RawTypeArguments* InstantiateFrom(
NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
@ -7206,16 +7189,14 @@ class TypeArguments : public Instance {
// Runtime instantiation with canonicalization. Not to be used during type
// finalization at compile time.
RawTypeArguments* InstantiateAndCanonicalizeFrom(
NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments) const;
// Each cached instantiation consists of a 4-tuple in the instantiations_
// Each cached instantiation consists of a 3-tuple in the instantiations_
// array stored in each canonical uninstantiated type argument vector.
enum Instantiation {
kInstantiatorTypeArgsIndex = 0,
kFunctionTypeArgsIndex,
kNnbdModeIndex,
kInstantiatedTypeArgsIndex,
kSizeInWords,
};
@ -7362,9 +7343,7 @@ class AbstractType : public Instance {
// must remain uninstantiated, because only T is a free variable in this type.
//
// Return a new type, or return 'this' if it is already instantiated.
// TODO(regis): mode is not needed anymore. Remove it here and in all callers.
virtual RawAbstractType* InstantiateFrom(
NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
@ -7509,14 +7488,11 @@ class AbstractType : public Instance {
RawAbstractType* UnwrapFutureOr() const;
// Check the subtype relationship.
bool IsSubtypeOf(NNBDMode mode,
const AbstractType& other,
Heap::Space space) const;
bool IsSubtypeOf(const AbstractType& other, Heap::Space space) const;
// Returns true iff subtype is a subtype of supertype, false otherwise or if
// an error occurred.
static bool InstantiateAndTestSubtype(
NNBDMode mode,
AbstractType* subtype,
AbstractType* supertype,
const TypeArguments& instantiator_type_args,
@ -7537,7 +7513,6 @@ class AbstractType : public Instance {
// Returns true if this type is a subtype of FutureOr<T> specified by 'other'.
// Returns false if other type is not a FutureOr.
bool IsSubtypeOfFutureOr(Zone* zone,
NNBDMode mode,
const AbstractType& other,
Heap::Space space) const;
@ -7615,7 +7590,6 @@ class Type : public AbstractType {
return signature() != Function::null();
}
virtual RawAbstractType* InstantiateFrom(
NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
@ -7767,7 +7741,6 @@ class TypeRef : public AbstractType {
return !ref_type.IsNull() && ref_type.IsFunctionType();
}
virtual RawTypeRef* InstantiateFrom(
NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
@ -7847,7 +7820,6 @@ class TypeParameter : public AbstractType {
TrailPtr trail = NULL) const;
virtual bool IsRecursive() const { return false; }
virtual RawAbstractType* InstantiateFrom(
NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,

View file

@ -967,7 +967,7 @@ void CallSiteResetter::Reset(const ICData& ic) {
args_desc_array_ = ic.arguments_descriptor();
ArgumentsDescriptor args_desc(args_desc_array_);
if (new_target_.IsNull() ||
!new_target_.AreValidArguments(NNBDMode::kLegacyLib, args_desc, NULL)) {
!new_target_.AreValidArguments(args_desc, NULL)) {
// TODO(rmacnak): Patch to a NSME stub.
VTIR_Print("Cannot rebind static call to %s from %s\n",
old_target_.ToCString(),

View file

@ -202,7 +202,6 @@ void TypeArguments::PrintJSONImpl(JSONStream* stream, bool ref) const {
Array& prior_instantiations = Array::Handle(instantiations());
ASSERT(prior_instantiations.Length() > 0); // Always at least a sentinel.
TypeArguments& type_args = TypeArguments::Handle();
Smi& nnbd_mode_as_smi = Smi::Handle();
intptr_t i = 0;
while (prior_instantiations.At(i) !=
Smi::New(TypeArguments::kNoInstantiator)) {
@ -213,13 +212,6 @@ void TypeArguments::PrintJSONImpl(JSONStream* stream, bool ref) const {
type_args ^= prior_instantiations.At(
i + TypeArguments::Instantiation::kFunctionTypeArgsIndex);
instantiation.AddProperty("functionTypeArguments", type_args, true);
nnbd_mode_as_smi ^= prior_instantiations.At(
i + TypeArguments::Instantiation::kNnbdModeIndex);
instantiation.AddProperty(
"nnbd_mode", nnbd_mode_as_smi.Value() ==
static_cast<intptr_t>(NNBDMode::kLegacyLib)
? "legacy"
: "opted-in");
type_args ^= prior_instantiations.At(
i + TypeArguments::Instantiation::kInstantiatedTypeArgsIndex);
instantiation.AddProperty("instantiated", type_args, true);

View file

@ -2158,7 +2158,7 @@ class RawTypeArguments : public RawInstance {
VISIT_FROM(RawObject*, instantiations_)
// The instantiations_ array remains empty for instantiated type arguments.
RawArray* instantiations_; // Of 4-tuple: 2 instantiators, mode, result.
RawArray* instantiations_; // Of 3-tuple: 2 instantiators, result.
RawSmi* length_;
RawSmi* hash_;

View file

@ -42,8 +42,7 @@ RawFunction* Resolver::ResolveDynamicForReceiverClass(
zone,
ResolveDynamicAnyArgs(zone, receiver_class, function_name, allow_add));
if (function.IsNull() ||
!function.AreValidArguments(NNBDMode::kLegacyLib, args_desc, NULL)) {
if (function.IsNull() || !function.AreValidArguments(args_desc, NULL)) {
// Return a null function to signal to the upper levels to dispatch to
// "noSuchMethod" function.
if (FLAG_trace_resolving) {
@ -51,8 +50,7 @@ RawFunction* Resolver::ResolveDynamicForReceiverClass(
String::Handle(zone, Symbols::New(thread, "function not found"));
if (!function.IsNull()) {
// Obtain more detailed error message.
function.AreValidArguments(NNBDMode::kLegacyLib, args_desc,
&error_message);
function.AreValidArguments(args_desc, &error_message);
}
THR_Print("ResolveDynamic error '%s': %s.\n", function_name.ToCString(),
error_message.ToCString());
@ -151,14 +149,13 @@ RawFunction* Resolver::ResolveStatic(const Library& library,
const Object& object = Object::Handle(library.ResolveName(function_name));
if (!object.IsNull() && object.IsFunction()) {
function ^= object.raw();
if (!function.AreValidArguments(NNBDMode::kLegacyLib, type_args_len,
num_arguments, argument_names, NULL)) {
if (!function.AreValidArguments(type_args_len, num_arguments,
argument_names, NULL)) {
if (FLAG_trace_resolving) {
String& error_message = String::Handle();
// Obtain more detailed error message.
function.AreValidArguments(NNBDMode::kLegacyLib, type_args_len,
num_arguments, argument_names,
&error_message);
function.AreValidArguments(type_args_len, num_arguments,
argument_names, &error_message);
THR_Print("ResolveStatic error '%s': %s.\n",
function_name.ToCString(), error_message.ToCString());
}
@ -199,16 +196,15 @@ RawFunction* Resolver::ResolveStatic(const Class& cls,
const Function& function =
Function::Handle(cls.LookupStaticFunction(function_name));
if (function.IsNull() ||
!function.AreValidArguments(NNBDMode::kLegacyLib, type_args_len,
num_arguments, argument_names, NULL)) {
!function.AreValidArguments(type_args_len, num_arguments, argument_names,
NULL)) {
// Return a null function to signal to the upper levels to throw a
// resolution error or maybe throw the error right here.
if (FLAG_trace_resolving) {
String& error_message = String::Handle(String::New("function not found"));
if (!function.IsNull()) {
// Obtain more detailed error message.
function.AreValidArguments(NNBDMode::kLegacyLib, type_args_len,
num_arguments, argument_names,
function.AreValidArguments(type_args_len, num_arguments, argument_names,
&error_message);
}
THR_Print("ResolveStatic error '%s': %s.\n", function_name.ToCString(),

View file

@ -372,24 +372,21 @@ END_LEAF_RUNTIME_ENTRY
// Arg0: uninstantiated type.
// Arg1: instantiator type arguments.
// Arg2: function type arguments.
// Arg3: nnbd mode as Smi.
// Return value: instantiated type.
DEFINE_RUNTIME_ENTRY(InstantiateType, 4) {
DEFINE_RUNTIME_ENTRY(InstantiateType, 3) {
AbstractType& type = AbstractType::CheckedHandle(zone, arguments.ArgAt(0));
const TypeArguments& instantiator_type_arguments =
TypeArguments::CheckedHandle(zone, arguments.ArgAt(1));
const TypeArguments& function_type_arguments =
TypeArguments::CheckedHandle(zone, arguments.ArgAt(2));
const NNBDMode nnbd_mode = static_cast<NNBDMode>(
Smi::CheckedHandle(zone, arguments.ArgAt(3)).Value());
ASSERT(!type.IsNull());
ASSERT(instantiator_type_arguments.IsNull() ||
instantiator_type_arguments.IsInstantiated());
ASSERT(function_type_arguments.IsNull() ||
function_type_arguments.IsInstantiated());
type =
type.InstantiateFrom(nnbd_mode, instantiator_type_arguments,
function_type_arguments, kAllFree, NULL, Heap::kOld);
type.InstantiateFrom(instantiator_type_arguments, function_type_arguments,
kAllFree, NULL, Heap::kOld);
if (type.IsTypeRef()) {
type = TypeRef::Cast(type).type();
ASSERT(!type.IsTypeRef());
@ -403,17 +400,14 @@ DEFINE_RUNTIME_ENTRY(InstantiateType, 4) {
// Arg0: uninstantiated type arguments.
// Arg1: instantiator type arguments.
// Arg2: function type arguments.
// Arg3: nnbd mode as Smi.
// Return value: instantiated type arguments.
DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 4) {
DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 3) {
TypeArguments& type_arguments =
TypeArguments::CheckedHandle(zone, arguments.ArgAt(0));
const TypeArguments& instantiator_type_arguments =
TypeArguments::CheckedHandle(zone, arguments.ArgAt(1));
const TypeArguments& function_type_arguments =
TypeArguments::CheckedHandle(zone, arguments.ArgAt(2));
const NNBDMode nnbd_mode = static_cast<NNBDMode>(
Smi::CheckedHandle(zone, arguments.ArgAt(3)).Value());
ASSERT(!type_arguments.IsNull() && !type_arguments.IsInstantiated());
ASSERT(instantiator_type_arguments.IsNull() ||
instantiator_type_arguments.IsInstantiated());
@ -423,7 +417,7 @@ DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 4) {
// instantiator can be reused as type argument vector.
ASSERT(!type_arguments.IsUninstantiatedIdentity());
type_arguments = type_arguments.InstantiateAndCanonicalizeFrom(
nnbd_mode, instantiator_type_arguments, function_type_arguments);
instantiator_type_arguments, function_type_arguments);
ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated());
arguments.SetReturn(type_arguments);
}
@ -434,9 +428,8 @@ DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 4) {
// Arg2: type to be a subtype of the other
// Arg3: type to be a supertype of the other
// Arg4: variable name of the subtype parameter
// Arg5: nnbd mode as Smi
// No return value.
DEFINE_RUNTIME_ENTRY(SubtypeCheck, 6) {
DEFINE_RUNTIME_ENTRY(SubtypeCheck, 5) {
const TypeArguments& instantiator_type_args =
TypeArguments::CheckedHandle(zone, arguments.ArgAt(0));
const TypeArguments& function_type_args =
@ -445,16 +438,13 @@ DEFINE_RUNTIME_ENTRY(SubtypeCheck, 6) {
AbstractType& supertype =
AbstractType::CheckedHandle(zone, arguments.ArgAt(3));
const String& dst_name = String::CheckedHandle(zone, arguments.ArgAt(4));
const NNBDMode nnbd_mode = static_cast<NNBDMode>(
Smi::CheckedHandle(zone, arguments.ArgAt(5)).Value());
ASSERT(!subtype.IsNull());
ASSERT(!supertype.IsNull());
// The supertype or subtype may not be instantiated.
if (AbstractType::InstantiateAndTestSubtype(nnbd_mode, &subtype, &supertype,
instantiator_type_args,
function_type_args)) {
if (AbstractType::InstantiateAndTestSubtype(
&subtype, &supertype, instantiator_type_args, function_type_args)) {
return;
}
@ -547,8 +537,7 @@ DEFINE_RUNTIME_ENTRY(ResolveCallFunction, 2) {
do {
call_function = cls.LookupDynamicFunction(Symbols::Call());
if (!call_function.IsNull()) {
if (!call_function.AreValidArguments(NNBDMode::kLegacyLib, args_desc,
NULL)) {
if (!call_function.AreValidArguments(args_desc, NULL)) {
call_function = Function::null();
}
break;
@ -560,7 +549,6 @@ DEFINE_RUNTIME_ENTRY(ResolveCallFunction, 2) {
// Helper routine for tracing a type check.
static void PrintTypeCheck(const char* message,
NNBDMode mode,
const Instance& instance,
const AbstractType& type,
const TypeArguments& instantiator_type_arguments,
@ -585,9 +573,9 @@ static void PrintTypeCheck(const char* message,
} else {
// Instantiate type before printing.
const AbstractType& instantiated_type =
AbstractType::Handle(type.InstantiateFrom(
mode, instantiator_type_arguments, function_type_arguments,
kAllFree, NULL, Heap::kOld));
AbstractType::Handle(type.InstantiateFrom(instantiator_type_arguments,
function_type_arguments,
kAllFree, NULL, Heap::kOld));
OS::PrintErr("%s: '%s' %s '%s' instantiated from '%s' (pc: %#" Px ").\n",
message, String::Handle(instance_type.Name()).ToCString(),
(result.raw() == Bool::True().raw()) ? "is" : "is !",
@ -608,7 +596,6 @@ static void PrintTypeCheck(const char* message,
// This operation is currently very slow (lookup of code is not efficient yet).
static void UpdateTypeTestCache(
Zone* zone,
NNBDMode mode,
const Instance& instance,
const AbstractType& type,
const TypeArguments& instantiator_type_arguments,
@ -696,7 +683,7 @@ static void UpdateTypeTestCache(
(last_instance_delayed_type_arguments.raw() ==
instance_delayed_type_arguments.raw())) {
OS::PrintErr(" Error in test cache %p ix: %" Pd ",", new_cache.raw(), i);
PrintTypeCheck(" duplicate cache entry", mode, instance, type,
PrintTypeCheck(" duplicate cache entry", instance, type,
instantiator_type_arguments, function_type_arguments,
result);
UNREACHABLE();
@ -711,7 +698,7 @@ static void UpdateTypeTestCache(
if (FLAG_trace_type_checks) {
AbstractType& test_type = AbstractType::Handle(zone, type.raw());
if (!test_type.IsInstantiated()) {
test_type = type.InstantiateFrom(mode, instantiator_type_arguments,
test_type = type.InstantiateFrom(instantiator_type_arguments,
function_type_arguments, kAllFree, NULL,
Heap::kNew);
}
@ -750,9 +737,8 @@ static void UpdateTypeTestCache(
// Arg2: type arguments of the instantiator of the type.
// Arg3: type arguments of the function of the type.
// Arg4: SubtypeTestCache.
// Arg5: nnbd mode as Smi.
// Return value: true or false, or may throw a type error in checked mode.
DEFINE_RUNTIME_ENTRY(Instanceof, 6) {
// Return value: true or false.
DEFINE_RUNTIME_ENTRY(Instanceof, 5) {
const Instance& instance = Instance::CheckedHandle(zone, arguments.ArgAt(0));
const AbstractType& type =
AbstractType::CheckedHandle(zone, arguments.ArgAt(1));
@ -762,20 +748,16 @@ DEFINE_RUNTIME_ENTRY(Instanceof, 6) {
TypeArguments::CheckedHandle(zone, arguments.ArgAt(3));
const SubtypeTestCache& cache =
SubtypeTestCache::CheckedHandle(zone, arguments.ArgAt(4));
const NNBDMode nnbd_mode = static_cast<NNBDMode>(
Smi::CheckedHandle(zone, arguments.ArgAt(5)).Value());
ASSERT(type.IsFinalized());
ASSERT(!type.IsDynamicType()); // No need to check assignment.
const Bool& result = Bool::Get(instance.IsInstanceOf(
nnbd_mode, type, instantiator_type_arguments, function_type_arguments));
type, instantiator_type_arguments, function_type_arguments));
if (FLAG_trace_type_checks) {
PrintTypeCheck("InstanceOf", nnbd_mode, instance, type,
instantiator_type_arguments, function_type_arguments,
result);
PrintTypeCheck("InstanceOf", instance, type, instantiator_type_arguments,
function_type_arguments, result);
}
UpdateTypeTestCache(zone, nnbd_mode, instance, type,
instantiator_type_arguments, function_type_arguments,
result, cache);
UpdateTypeTestCache(zone, instance, type, instantiator_type_arguments,
function_type_arguments, result, cache);
arguments.SetReturn(result);
}
@ -789,9 +771,8 @@ DEFINE_RUNTIME_ENTRY(Instanceof, 6) {
// Arg4: name of variable being assigned to.
// Arg5: SubtypeTestCache.
// Arg6: invocation mode (see TypeCheckMode)
// Arg7: nnbd mode as Smi.
// Return value: instance if a subtype, otherwise throw a TypeError.
DEFINE_RUNTIME_ENTRY(TypeCheck, 8) {
DEFINE_RUNTIME_ENTRY(TypeCheck, 7) {
const Instance& src_instance =
Instance::CheckedHandle(zone, arguments.ArgAt(0));
AbstractType& dst_type =
@ -815,19 +796,15 @@ DEFINE_RUNTIME_ENTRY(TypeCheck, 8) {
ASSERT(mode == kTypeCheckFromInline);
#endif
const NNBDMode nnbd_mode = static_cast<NNBDMode>(
Smi::CheckedHandle(zone, arguments.ArgAt(7)).Value());
ASSERT(!dst_type.IsDynamicType()); // No need to check assignment.
// A null instance is already detected and allowed in inlined code, unless
// strong checking is enabled.
ASSERT(!src_instance.IsNull() || FLAG_null_safety);
const bool is_instance_of = src_instance.IsAssignableTo(
nnbd_mode, dst_type, instantiator_type_arguments,
function_type_arguments);
dst_type, instantiator_type_arguments, function_type_arguments);
if (FLAG_trace_type_checks) {
PrintTypeCheck("TypeCheck", nnbd_mode, src_instance, dst_type,
PrintTypeCheck("TypeCheck", src_instance, dst_type,
instantiator_type_arguments, function_type_arguments,
Bool::Get(is_instance_of));
}
@ -838,9 +815,9 @@ DEFINE_RUNTIME_ENTRY(TypeCheck, 8) {
AbstractType::Handle(zone, src_instance.GetType(Heap::kNew));
if (!dst_type.IsInstantiated()) {
// Instantiate dst_type before reporting the error.
dst_type = dst_type.InstantiateFrom(
nnbd_mode, instantiator_type_arguments, function_type_arguments,
kAllFree, NULL, Heap::kNew);
dst_type = dst_type.InstantiateFrom(instantiator_type_arguments,
function_type_arguments, kAllFree,
NULL, Heap::kNew);
}
if (dst_name.IsNull()) {
#if !defined(TARGET_ARCH_IA32)
@ -940,7 +917,7 @@ DEFINE_RUNTIME_ENTRY(TypeCheck, 8) {
#endif
}
UpdateTypeTestCache(zone, nnbd_mode, src_instance, dst_type,
UpdateTypeTestCache(zone, src_instance, dst_type,
instantiator_type_arguments, function_type_arguments,
Bool::True(), cache);
}
@ -1235,18 +1212,8 @@ static void TrySwitchInstanceCall(const ICData& ic_data,
static RawFunction* ComputeTypeCheckTarget(const Instance& receiver,
const AbstractType& type,
const ArgumentsDescriptor& desc) {
// If the instance is not null, the result of _simpleInstanceOf does not
// depend on the nnbd mode, because we only check against a rare type,
// i.e. a class. However, we need to determine the correct nnbd mode when
// the instance is null.
// Since type literals are not imported, a legacy type indicates that the
// call originated in a legacy library. Note that the type test against a
// non-legacy type (even in a legacy library) such as dynamic, void, or Null
// yield the same result independently of the mode used.
const NNBDMode mode =
type.IsLegacy() ? NNBDMode::kLegacyLib : NNBDMode::kOptedInLib;
const bool result = receiver.IsInstanceOf(
mode, type, Object::null_type_arguments(), Object::null_type_arguments());
const bool result = receiver.IsInstanceOf(type, Object::null_type_arguments(),
Object::null_type_arguments());
const ObjectStore* store = Isolate::Current()->object_store();
const Function& target =
Function::Handle(result ? store->simple_instance_of_true_function()
@ -2126,8 +2093,7 @@ DEFINE_RUNTIME_ENTRY(NoSuchMethodFromCallStub, 4) {
while (!cls.IsNull()) {
function = cls.LookupDynamicFunction(target_name);
if (!function.IsNull()) {
ASSERT(
!function.AreValidArguments(NNBDMode::kLegacyLib, args_desc, NULL));
ASSERT(!function.AreValidArguments(args_desc, NULL));
break; // mismatch, invoke noSuchMethod
}
function = cls.LookupDynamicFunction(getter_name);

View file

@ -269,8 +269,7 @@ void TypeTestingStubGenerator::BuildOptimizedTypeTestStubFastCases(
/*exclude_null=*/!Instance::NullIsAssignableTo(type));
const Type& int_type = Type::Handle(Type::IntType());
const bool smi_is_ok =
int_type.IsSubtypeOf(NNBDMode::kLegacyLib, type, Heap::kNew);
const bool smi_is_ok = int_type.IsSubtypeOf(type, Heap::kNew);
BuildOptimizedSubtypeRangeCheck(assembler, ranges, class_id_reg,
instance_reg, smi_is_ok);
@ -358,7 +357,7 @@ void TypeTestingStubGenerator::
// uncommon because most Dart code in 2.0 will be strongly typed)!
__ CompareObject(instance_type_args_reg, Object::null_object());
const Type& rare_type = Type::Handle(Type::RawCast(type_class.RareType()));
if (rare_type.IsSubtypeOf(NNBDMode::kLegacyLib, type, Heap::kNew)) {
if (rare_type.IsSubtypeOf(type, Heap::kNew)) {
compiler::Label process_done;
__ BranchIf(NOT_EQUAL, &process_done);
__ Ret();

View file

@ -64,8 +64,8 @@ class Object {
// Call this function instead of inlining instanceof, thus collecting
// type feedback and reducing code size of unoptimized code.
@pragma("vm:entry-point", "call")
bool _instanceOf(instantiatorTypeArguments, functionTypeArguments, type,
nnbd_mode) native "Object_instanceOf";
bool _instanceOf(instantiatorTypeArguments, functionTypeArguments, type)
native "Object_instanceOf";
// Group of functions for implementing fast simple instance of.
@pragma("vm:entry-point", "call")

View file

@ -62,8 +62,8 @@ class Object {
// Call this function instead of inlining instanceof, thus collecting
// type feedback and reducing code size of unoptimized code.
@pragma("vm:entry-point", "call")
bool _instanceOf(instantiatorTypeArguments, functionTypeArguments, type,
nnbd_mode) native "Object_instanceOf";
bool _instanceOf(instantiatorTypeArguments, functionTypeArguments, type)
native "Object_instanceOf";
// Group of functions for implementing fast simple instance of.
@pragma("vm:entry-point", "call")

View file

@ -35,5 +35,5 @@ MINOR 8
PATCH 0
PRERELEASE 0
PRERELEASE_PATCH 0
ABI_VERSION 28
OLDEST_SUPPORTED_ABI_VERSION 28
ABI_VERSION 29
OLDEST_SUPPORTED_ABI_VERSION 29