mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 22:00:09 +00:00
[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:
parent
5cd6b309fb
commit
5701c4fd3b
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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 []
|
||||
|
|
|
@ -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()));
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
{
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) |
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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); \
|
||||
} \
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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_; }
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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_;
|
||||
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue