[vm/compiler] Support unboxing of return values of getters
This CL adds support for unboxing of return values of getters and therefore completes the work on unboxing support for normal members (closures are still missing). As with existing unboxing support for methods and setters, we utilize TFA information to proof a getter will always return non-nullable int/double. We then make such a getter return unboxed int/double. If there are dynamic calls to the getter a dyn:get:* forwarder will be created which performs boxing of the return value. Overall this reduces RX by eliminating BoxInt64 instructions. It sometimes increases metadata due to more dyn:get:* function objects. => On our main size benchmark targets show no significant change. Issue https://github.com/dart-lang/sdk/issues/40876 Change-Id: If7450ef7e5e3fc9c2e0eaa6b86ffa817699a7e17 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/154329 Commit-Queue: Martin Kustermann <kustermann@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com> Reviewed-by: Tess Strickland <sstrickl@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
3849b5061c
commit
f955b82a92
@@ -309,6 +309,13 @@ class AnnotateKernel extends RecursiveVisitor<Null> {
|
||||
if (_typeFlowAnalysis.isMemberUsed(member)) {
|
||||
if (member is Field) {
|
||||
_setInferredType(member, _typeFlowAnalysis.fieldType(member));
|
||||
|
||||
final unboxingInfoMetadata =
|
||||
_unboxingInfo.getUnboxingInfoOfMember(member);
|
||||
if (unboxingInfoMetadata != null &&
|
||||
!unboxingInfoMetadata.isFullyBoxed) {
|
||||
_unboxingInfoMetadata.mapping[member] = unboxingInfoMetadata;
|
||||
}
|
||||
} else {
|
||||
Args<Type> argTypes = _typeFlowAnalysis.argumentTypes(member);
|
||||
final uncheckedParameters =
|
||||
@@ -532,32 +539,42 @@ void _makePartition(Component component, TypeFlowAnalysis typeFlowAnalysis,
|
||||
|
||||
void _updateUnboxingInfoOfMember(Member member,
|
||||
TypeFlowAnalysis typeFlowAnalysis, UnboxingInfoManager unboxingInfo) {
|
||||
if (typeFlowAnalysis.isMemberUsed(member) && (member is! Field)) {
|
||||
final Args<Type> argTypes = typeFlowAnalysis.argumentTypes(member);
|
||||
assertx(argTypes != null);
|
||||
if (typeFlowAnalysis.isMemberUsed(member)) {
|
||||
if (member is Procedure || member is Constructor) {
|
||||
final Args<Type> argTypes = typeFlowAnalysis.argumentTypes(member);
|
||||
assertx(argTypes != null);
|
||||
|
||||
final int firstParamIndex =
|
||||
numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0);
|
||||
final int firstParamIndex =
|
||||
numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0);
|
||||
|
||||
final positionalParams = member.function.positionalParameters;
|
||||
assertx(
|
||||
argTypes.positionalCount == firstParamIndex + positionalParams.length);
|
||||
final positionalParams = member.function.positionalParameters;
|
||||
assertx(argTypes.positionalCount ==
|
||||
firstParamIndex + positionalParams.length);
|
||||
|
||||
for (int i = 0; i < positionalParams.length; i++) {
|
||||
final inferredType = argTypes.values[firstParamIndex + i];
|
||||
unboxingInfo.applyToArg(member, i, inferredType);
|
||||
for (int i = 0; i < positionalParams.length; i++) {
|
||||
final inferredType = argTypes.values[firstParamIndex + i];
|
||||
unboxingInfo.applyToArg(member, i, inferredType);
|
||||
}
|
||||
|
||||
final names = argTypes.names;
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
final inferredType =
|
||||
argTypes.values[firstParamIndex + positionalParams.length + i];
|
||||
unboxingInfo.applyToArg(
|
||||
member, positionalParams.length + i, inferredType);
|
||||
}
|
||||
|
||||
final Type resultType = typeFlowAnalysis.getSummary(member).resultType;
|
||||
unboxingInfo.applyToReturn(member, resultType);
|
||||
} else if (member is Field) {
|
||||
final fieldValue = typeFlowAnalysis.getFieldValue(member).value;
|
||||
if (member.hasSetter) {
|
||||
unboxingInfo.applyToArg(member, 0, fieldValue);
|
||||
}
|
||||
unboxingInfo.applyToReturn(member, fieldValue);
|
||||
} else {
|
||||
assertx(false);
|
||||
}
|
||||
|
||||
final names = argTypes.names;
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
final inferredType =
|
||||
argTypes.values[firstParamIndex + positionalParams.length + i];
|
||||
unboxingInfo.applyToArg(
|
||||
member, positionalParams.length + i, inferredType);
|
||||
}
|
||||
|
||||
final Type resultType = typeFlowAnalysis.getSummary(member).resultType;
|
||||
unboxingInfo.applyToReturn(member, resultType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:kernel/ast.dart';
|
||||
import 'package:kernel/core_types.dart';
|
||||
import 'package:kernel/external_name.dart' show getExternalName;
|
||||
@@ -133,10 +131,12 @@ class UnboxingInfoManager {
|
||||
for (final superType in cls.supers) {
|
||||
final superClass = superType.classNode;
|
||||
bool linked = false;
|
||||
superClass.procedures.forEach((Procedure procedure) {
|
||||
if (member.name == procedure.name) {
|
||||
_linkMembers(member, procedure);
|
||||
linked = true;
|
||||
superClass.members.forEach((Member superMember) {
|
||||
if (member.isInstanceMember) {
|
||||
if (member.name == superMember.name) {
|
||||
_linkMembers(member, superMember);
|
||||
linked = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!linked) {
|
||||
@@ -158,17 +158,10 @@ class UnboxingInfoManager {
|
||||
}
|
||||
|
||||
Member _validMemberOrNull(Member member) {
|
||||
if (member == null || (member is! Procedure && member is! Constructor)) {
|
||||
if (member == null ||
|
||||
(member is! Procedure && member is! Constructor && member is! Field)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO(dartbug.com/33549): Support setters with unboxed arguments
|
||||
// For this, fields should also be considered in the partition
|
||||
// and be annotated with the UnboxingInfoMetadata.
|
||||
if (member is Procedure && (member.isSetter || member.isGetter)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return member;
|
||||
}
|
||||
|
||||
@@ -187,7 +180,9 @@ class UnboxingInfoManager {
|
||||
final int memberId = _allUnboxingInfo.length;
|
||||
assertx(memberId == _partitionIds.length);
|
||||
assertx(_partitionIds.length == _partitionRank.length);
|
||||
final int argsLen = member.function.requiredParameterCount;
|
||||
final int argsLen = member is Field
|
||||
? (member.hasSetter ? 1 : 0)
|
||||
: member.function.requiredParameterCount;
|
||||
_memberIds[member] = memberId;
|
||||
_allUnboxingInfo.add(UnboxingInfoMetadata(argsLen));
|
||||
_partitionIds.add(memberId);
|
||||
@@ -202,9 +197,7 @@ class UnboxingInfoManager {
|
||||
// have boxed parameters and return values.
|
||||
return (_isNative(member) ||
|
||||
_nativeCodeOracle.isMemberReferencedFromNativeCode(member) ||
|
||||
_isEnclosingClassSubtypeOfNum(member) ||
|
||||
(!_isConstructorOrStatic(member) &&
|
||||
!_needsDynamicInvocationForwarder(member)));
|
||||
_isEnclosingClassSubtypeOfNum(member));
|
||||
}
|
||||
|
||||
bool _isNative(Member member) {
|
||||
@@ -221,30 +214,6 @@ class UnboxingInfoManager {
|
||||
.isSubtypeOf(_typeHierarchy, _coreTypes.numClass));
|
||||
}
|
||||
|
||||
bool _needsDynamicInvocationForwarder(Procedure procedure) {
|
||||
for (var param in procedure.function.positionalParameters) {
|
||||
if (!_isTopTypeForAssignability(param.type) &&
|
||||
!param.isCovariant &&
|
||||
!param.isGenericCovariantImpl) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (var param in procedure.function.namedParameters) {
|
||||
if (!_isTopTypeForAssignability(param.type) &&
|
||||
!param.isCovariant &&
|
||||
!param.isGenericCovariantImpl) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool _isTopTypeForAssignability(DartType type) {
|
||||
return (_coreTypes.isTop(type) || (type == Object) || (type == FutureOr));
|
||||
}
|
||||
|
||||
int _getMemberId(Member member) {
|
||||
return _memberIds[member];
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ bool hasReceiverArg(Member member) =>
|
||||
// Type arguments to procedures is only supported for factory constructors of
|
||||
// generic classes at the moment.
|
||||
//
|
||||
// TODO(sjindel/tfa): Extend suport to normal generic functions.
|
||||
// TODO(sjindel/tfa): Extend support to normal generic functions.
|
||||
int numTypeParams(Member member) => member is Procedure && member.isFactory
|
||||
? member.function.typeParameters.length
|
||||
: 0;
|
||||
|
||||
@@ -6,8 +6,8 @@ import "dart:typed_data" as typ;
|
||||
import "dart:typed_data";
|
||||
|
||||
class _Vector extends core::Object {
|
||||
[@vm.inferred-type.metadata=dart.core::_Smi (value: 0)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] final field core::int* _offset;
|
||||
[@vm.inferred-type.metadata=dart.core::_Smi (value: 10)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] final field core::int* _length;
|
||||
[@vm.inferred-type.metadata=dart.core::_Smi (value: 0)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] [@vm.unboxing-info.metadata=()->i] final field core::int* _offset;
|
||||
[@vm.inferred-type.metadata=dart.core::_Smi (value: 10)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] [@vm.unboxing-info.metadata=()->i] final field core::int* _length;
|
||||
[@vm.inferred-type.metadata=dart.typed_data::_Float64List] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8,getterSelectorId:9] final field core::List<core::double*>* _elements;
|
||||
[@vm.unboxing-info.metadata=(i)->b] constructor •([@vm.inferred-type.metadata=dart.core::_Smi (value: 10)] core::int* size) → self::_Vector*
|
||||
: self::_Vector::_offset = 0, self::_Vector::_length = size, self::_Vector::_elements = [@vm.inferred-type.metadata=dart.typed_data::_Float64List] typ::Float64List::•(size), super core::Object::•()
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ class C2<T extends core::Object* = dynamic> extends core::Object {
|
||||
synthetic constructor •() → self::C2<self::C2::T*>*
|
||||
: super core::Object::•()
|
||||
;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] method id3([@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.0)] generic-covariant-impl core::Comparable<self::C2::T*>* x) → dynamic
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] [@vm.unboxing-info.metadata=(d)->d] method id3([@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.0)] generic-covariant-impl core::Comparable<self::C2::T*>* x) → dynamic
|
||||
return x;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] method id4([@vm.inferred-type.metadata=#lib::K<#lib::J*> (skip check)] generic-covariant-impl self::K<self::I<self::C2::T*>*>* x) → dynamic
|
||||
return x;
|
||||
|
||||
@@ -12,7 +12,7 @@ class A extends core::Object {
|
||||
return "bar";
|
||||
}
|
||||
class B extends core::Object /*isEnum*/ {
|
||||
[@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] final field core::int* index;
|
||||
[@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] [@vm.unboxing-info.metadata=()->i] final field core::int* index;
|
||||
[@vm.inferred-type.metadata=dart.core::_OneByteString (value: B.b2)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8,getterSelectorId:9] final field core::String* _name;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] method toString() → core::String*
|
||||
return [@vm.inferred-type.metadata=dart.core::_OneByteString (value: B.b2)] this.{=self::B::_name};
|
||||
@@ -26,7 +26,7 @@ static method test1([[@vm.inferred-type.metadata=dart.core::_Smi (value: 42)] co
|
||||
static method test2({[@vm.inferred-type.metadata=dart.core::_Smi (value: 43)] core::int* arg = #C2}) → void {
|
||||
core::print(arg);
|
||||
}
|
||||
static get getD() → dynamic
|
||||
[@vm.unboxing-info.metadata=()->d]static get getD() → dynamic
|
||||
return 100.0;
|
||||
[@vm.unboxing-info.metadata=(d)->b]static method testDouble([@vm.inferred-type.metadata=dart.core::_Double (value: 3.14)] core::double* arg) → void {
|
||||
core::print(arg);
|
||||
|
||||
@@ -6,20 +6,20 @@ abstract class A extends core::Object {
|
||||
synthetic constructor •() → self::A*
|
||||
: super core::Object::•()
|
||||
;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] abstract method foo() → core::int*;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] abstract method foo() → core::int*;
|
||||
}
|
||||
class B extends self::A {
|
||||
synthetic constructor •() → self::B*
|
||||
: super self::A::•()
|
||||
;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foo() → core::int*
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] method foo() → core::int*
|
||||
return 1;
|
||||
}
|
||||
class C extends core::Object implements self::A {
|
||||
synthetic constructor •() → self::C*
|
||||
: super core::Object::•()
|
||||
;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foo() → core::int*
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] method foo() → core::int*
|
||||
return 2;
|
||||
}
|
||||
class D extends self::C {
|
||||
|
||||
@@ -9,7 +9,7 @@ class C<T extends core::Object* = dynamic> extends core::Object {
|
||||
synthetic constructor •() → self::C<self::C::T*>*
|
||||
: super core::Object::•()
|
||||
;
|
||||
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method test2c([@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 3)] generic-covariant-impl FutureOr<self::C::T*>* x) → void {}
|
||||
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i)->b] method test2c([@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 3)] generic-covariant-impl FutureOr<self::C::T*>* x) → void {}
|
||||
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method test3c([@vm.inferred-type.metadata=dart.async::_Future<dart.core::int*> (skip check)] generic-covariant-impl asy::Future<self::C::T*>* x) → void {}
|
||||
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method test4c([@vm.inferred-type.metadata=dart.async::_Future<dart.core::int*> (skip check)] generic-covariant-impl FutureOr<self::C::T*>* x) → void {}
|
||||
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method test2r([@vm.inferred-type.metadata=#lib::C<dart.core::int*> (skip check)] generic-covariant-impl self::C<FutureOr<self::C::T*>*>* x) → void {}
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ abstract class TestNamedOrderBase extends core::Object {
|
||||
}
|
||||
}
|
||||
class TestNamedOrderSub extends self::TestNamedOrderBase {
|
||||
[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] field core::int* x;
|
||||
[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i)->i] field core::int* x;
|
||||
constructor •() → self::TestNamedOrderSub*
|
||||
: self::TestNamedOrderSub::x = [@vm.inferred-type.metadata=int] self::dec(), dynamic #t5 = [@vm.inferred-type.metadata=int] self::inc(), dynamic #t6 = [@vm.inferred-type.metadata=int] self::inc(), dynamic #t7 = [@vm.inferred-type.metadata=int] self::inc(), dynamic #t8 = [@vm.inferred-type.metadata=int] self::dec(), super self::TestNamedOrderBase::•(#t5, #t8, #t7, #t6) {
|
||||
exp::Expect::equals([@vm.direct-call.metadata=#lib::TestNamedOrderSub.x] [@vm.inferred-type.metadata=int] this.{self::TestNamedOrderSub::x}, 0);
|
||||
|
||||
@@ -39,7 +39,7 @@ abstract class A extends core::Object {
|
||||
;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] abstract method foo() → dynamic;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] abstract get bar() → dynamic;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] abstract method bazz(dynamic a1, dynamic a2, dynamic a3, [dynamic a4 = #C1, dynamic a5 = #C1]) → dynamic;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] [@vm.unboxing-info.metadata=(i,i,i)->b] abstract method bazz(dynamic a1, dynamic a2, dynamic a3, [dynamic a4 = #C1, dynamic a5 = #C1]) → dynamic;
|
||||
}
|
||||
class B extends self::A {
|
||||
synthetic constructor •() → self::B*
|
||||
@@ -52,7 +52,7 @@ class B extends self::A {
|
||||
return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 1, #C3, #C4, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))));
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] no-such-method-forwarder method foo() → dynamic
|
||||
return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C3, #C4, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))));
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] no-such-method-forwarder method bazz([@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] dynamic a1, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic a2, [@vm.inferred-type.metadata=dart.core::_Smi (value: 3)] dynamic a3, [[@vm.inferred-type.metadata=dart.core::_Smi (value: 4)] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::Null? (value: null)] dynamic a5 = #C1]) → dynamic
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] [@vm.unboxing-info.metadata=(i,i,i)->b] no-such-method-forwarder method bazz([@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] dynamic a1, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic a2, [@vm.inferred-type.metadata=dart.core::_Smi (value: 3)] dynamic a3, [[@vm.inferred-type.metadata=dart.core::_Smi (value: 4)] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::Null? (value: null)] dynamic a5 = #C1]) → dynamic
|
||||
return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[a1, a2, a3, a4, a5]), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))));
|
||||
}
|
||||
abstract class C extends core::Object {
|
||||
@@ -71,7 +71,7 @@ class D extends self::C implements self::A {
|
||||
return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 1, #C3, #C4, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))));
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] no-such-method-forwarder method foo() → dynamic
|
||||
return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C3, #C4, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))));
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] no-such-method-forwarder method bazz([@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] dynamic a1, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic a2, [@vm.inferred-type.metadata=dart.core::_Smi (value: 3)] dynamic a3, [[@vm.inferred-type.metadata=dart.core::_Smi (value: 4)] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::Null? (value: null)] dynamic a5 = #C1]) → dynamic
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] [@vm.unboxing-info.metadata=(i,i,i)->b] no-such-method-forwarder method bazz([@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] dynamic a1, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic a2, [@vm.inferred-type.metadata=dart.core::_Smi (value: 3)] dynamic a3, [[@vm.inferred-type.metadata=dart.core::_Smi (value: 4)] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::Null? (value: null)] dynamic a5 = #C1]) → dynamic
|
||||
return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[a1, a2, a3, a4, a5]), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))));
|
||||
}
|
||||
class E extends core::Object implements self::A {
|
||||
|
||||
+4
-4
@@ -65,10 +65,10 @@ class FooKeep extends pro::GeneratedMessage {
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:6] @#C14
|
||||
get mapKeep() → core::Map<core::String*, self::BarKeep*>*
|
||||
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getMap] [@vm.inferred-type.metadata=! (skip check)] this.{pro::GeneratedMessage::$_getMap}<core::String*, self::BarKeep*>(2);
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] @#C16
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=()->i] @#C16
|
||||
get aKeep() → core::int*
|
||||
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(4);
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] @#C16
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(i)->b] @#C16
|
||||
set aKeep([@vm.inferred-type.metadata=dart.core::_Smi (value: 43)] core::int* v) → void {
|
||||
[@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(4, v);
|
||||
}
|
||||
@@ -95,10 +95,10 @@ class BarKeep extends pro::GeneratedMessage {
|
||||
@#C10
|
||||
static method create() → self::BarKeep*
|
||||
return new self::BarKeep::_();
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] @#C12
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] [@vm.unboxing-info.metadata=()->i] @#C12
|
||||
get aKeep() → core::int*
|
||||
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(0);
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] @#C12
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] [@vm.unboxing-info.metadata=(i)->b] @#C12
|
||||
set aKeep([@vm.inferred-type.metadata=dart.core::_Smi] core::int* v) → void {
|
||||
[@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(0, v);
|
||||
}
|
||||
|
||||
+2
-2
@@ -62,7 +62,7 @@ class FooKeep extends pro::GeneratedMessage {
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:6] @#C15
|
||||
get mapKeep() → core::Map<core::String*, self::BarKeep*>*
|
||||
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getMap] [@vm.inferred-type.metadata=! (skip check)] this.{pro::GeneratedMessage::$_getMap}<core::String*, self::BarKeep*>(2);
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:7] @#C17
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:7] [@vm.unboxing-info.metadata=()->i] @#C17
|
||||
get aKeep() → core::int*
|
||||
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(4);
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8,getterSelectorId:9] @#C19
|
||||
@@ -92,7 +92,7 @@ class BarKeep extends pro::GeneratedMessage {
|
||||
@#C11
|
||||
static method create() → self::BarKeep*
|
||||
return new self::BarKeep::_();
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:12] @#C13
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:12] [@vm.unboxing-info.metadata=()->i] @#C13
|
||||
get aKeep() → core::int*
|
||||
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(0);
|
||||
}
|
||||
|
||||
+4
-4
@@ -72,7 +72,7 @@ class FooKeep extends pro::GeneratedMessage {
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5] @#C17
|
||||
get mapDrop() → core::Map<core::String*, self::ZopDrop*>*
|
||||
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getMap] [@vm.inferred-type.metadata=! (skip check)] this.{pro::GeneratedMessage::$_getMap}<core::String*, self::ZopDrop*>(3);
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6] @#C19
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6] [@vm.unboxing-info.metadata=(i)->b] @#C19
|
||||
set aKeep([@vm.inferred-type.metadata=dart.core::_Smi (value: 43)] core::int* v) → void {
|
||||
[@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(4, v);
|
||||
}
|
||||
@@ -101,11 +101,11 @@ class BarKeep extends pro::GeneratedMessage {
|
||||
@#C11
|
||||
static method create() → self::BarKeep*
|
||||
return new self::BarKeep::_();
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9] @#C13
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9] [@vm.unboxing-info.metadata=(i)->b] @#C13
|
||||
set aKeep([@vm.inferred-type.metadata=dart.core::_Smi] core::int* v) → void {
|
||||
[@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(0, v);
|
||||
}
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:10] @#C25
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:10] [@vm.unboxing-info.metadata=(i)->b] @#C25
|
||||
set bDrop([@vm.inferred-type.metadata=dart.core::_Smi (value: 4)] core::int* v) → void {
|
||||
[@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(1, v);
|
||||
}
|
||||
@@ -157,7 +157,7 @@ class ZopDrop extends pro::GeneratedMessage {
|
||||
@#C11
|
||||
static method create() → self::ZopDrop*
|
||||
return new self::ZopDrop::_();
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11] @#C13
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11] [@vm.unboxing-info.metadata=(i)->b] @#C13
|
||||
set aDrop([@vm.inferred-type.metadata=dart.core::_Smi (value: 3)] core::int* v) → void {
|
||||
[@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(0, v);
|
||||
}
|
||||
|
||||
+4
-4
@@ -69,10 +69,10 @@ class FooKeep extends pro::GeneratedMessage {
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:6] @#C14
|
||||
get mapKeep() → core::Map<core::String*, self::BarKeep*>*
|
||||
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getMap] [@vm.inferred-type.metadata=! (skip check)] this.{pro::GeneratedMessage::$_getMap}<core::String*, self::BarKeep*>(2);
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] @#C16
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=()->i] @#C16
|
||||
get aKeep() → core::int*
|
||||
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(4);
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] @#C16
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(i)->b] @#C16
|
||||
set aKeep([@vm.inferred-type.metadata=dart.core::_Smi (value: 43)] core::int* v) → void {
|
||||
[@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(4, v);
|
||||
}
|
||||
@@ -99,10 +99,10 @@ class BarKeep extends pro::GeneratedMessage {
|
||||
@#C10
|
||||
static method create() → self::BarKeep*
|
||||
return new self::BarKeep::_();
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] @#C12
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] [@vm.unboxing-info.metadata=()->i] @#C12
|
||||
get aKeep() → core::int*
|
||||
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(0);
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] @#C12
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] [@vm.unboxing-info.metadata=(i)->b] @#C12
|
||||
set aKeep([@vm.inferred-type.metadata=dart.core::_Smi] core::int* v) → void {
|
||||
[@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(0, v);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ class B extends core::Object {
|
||||
synthetic constructor •() → self::B*
|
||||
: super core::Object::•()
|
||||
;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] get x() → dynamic
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] [@vm.unboxing-info.metadata=()->i] get x() → dynamic
|
||||
return 0;
|
||||
}
|
||||
class A extends core::Object {
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ class B extends self::A {
|
||||
synthetic constructor •() → self::B*
|
||||
: super self::A::•()
|
||||
;
|
||||
[@vm.procedure-attributes.metadata=hasThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foo() → core::int*
|
||||
[@vm.procedure-attributes.metadata=hasThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] method foo() → core::int*
|
||||
return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=! (skip check)] 1.{core::num::+}([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult().foo() as{TypeError,ForDynamic} core::num) as{TypeError} core::int*;
|
||||
}
|
||||
class TearOffDynamicMethod extends core::Object {
|
||||
|
||||
+3
-3
@@ -7,15 +7,15 @@ abstract class A extends core::Object {
|
||||
synthetic constructor •() → self::A*
|
||||
: super core::Object::•()
|
||||
;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] abstract method foo() → core::int*;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] abstract method foo() → core::int*;
|
||||
}
|
||||
class B extends self::A {
|
||||
synthetic constructor •() → self::B*
|
||||
: super self::A::•()
|
||||
;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foo() → core::int*
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] method foo() → core::int*
|
||||
return _in::unsafeCast<core::int*>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 1.{core::num::+}(_in::unsafeCast<core::num>([@vm.direct-call.metadata=#lib::B.bar] [@vm.inferred-type.metadata=dart.core::_Smi (value: 3) (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult().bar())));
|
||||
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method bar() → core::int*
|
||||
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i] method bar() → core::int*
|
||||
return 3;
|
||||
}
|
||||
class TearOffInterfaceMethod extends core::Object {
|
||||
|
||||
+3
-3
@@ -7,20 +7,20 @@ abstract class A extends core::Object {
|
||||
synthetic constructor •() → self::A*
|
||||
: super core::Object::•()
|
||||
;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] abstract method foo() → core::int*;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] abstract method foo() → core::int*;
|
||||
}
|
||||
class B extends self::A {
|
||||
synthetic constructor •() → self::B*
|
||||
: super self::A::•()
|
||||
;
|
||||
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foo() → core::int*
|
||||
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] method foo() → core::int*
|
||||
return _in::unsafeCast<core::int*>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 1.{core::num::+}(_in::unsafeCast<core::num>([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=int? (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult().foo())));
|
||||
}
|
||||
abstract class Base extends core::Object {
|
||||
synthetic constructor •() → self::Base*
|
||||
: super core::Object::•()
|
||||
;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method foo() → core::int*
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i] method foo() → core::int*
|
||||
return _in::unsafeCast<core::int*>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 3.{core::num::+}(_in::unsafeCast<core::num>([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=int? (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult().foo())));
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method doCall(dynamic x) → core::int*
|
||||
return [@vm.call-site-attributes.metadata=receiverType:dynamic] x.call() as{TypeError,ForDynamic} core::int*;
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ class B<T extends core::Object* = dynamic> extends self::A<self::B::T*> {
|
||||
synthetic constructor •() → self::B<self::B::T*>*
|
||||
: super self::A::•()
|
||||
;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method testT1([@vm.inferred-type.metadata=dart.core::_Smi (value: 42)] dynamic x) → dynamic
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i)->i] method testT1([@vm.inferred-type.metadata=dart.core::_Smi (value: 42)] dynamic x) → dynamic
|
||||
return _in::unsafeCast<self::B::T*>(x);
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method testT2negative([@vm.inferred-type.metadata=#lib::A<dart.core::String*>] dynamic x) → dynamic
|
||||
return x as self::B::T*;
|
||||
|
||||
+2
-2
@@ -12,13 +12,13 @@ class B<T extends core::Object? = dynamic> extends self::A<self::B::T%> {
|
||||
synthetic constructor •() → self::B<self::B::T%>
|
||||
: super self::A::•()
|
||||
;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method testT1([@vm.inferred-type.metadata=dart.core::_Smi (value: 42)] dynamic x) → dynamic
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i)->i] method testT1([@vm.inferred-type.metadata=dart.core::_Smi (value: 42)] dynamic x) → dynamic
|
||||
return _in::unsafeCast<self::B::T%>(x);
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method testT2([@vm.inferred-type.metadata=dart.core::Null? (value: null)] dynamic x) → dynamic
|
||||
return _in::unsafeCast<self::B::T%>(x);
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method testT3([@vm.inferred-type.metadata=dart.core::Null? (value: null)] dynamic x) → dynamic
|
||||
return _in::unsafeCast<self::B::T%>(x);
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method testNullableT1([@vm.inferred-type.metadata=dart.core::_Smi (value: 42)] dynamic x) → dynamic
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(i)->i] method testNullableT1([@vm.inferred-type.metadata=dart.core::_Smi (value: 42)] dynamic x) → dynamic
|
||||
return _in::unsafeCast<self::B::T?>(x);
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method testNullableT2([@vm.inferred-type.metadata=dart.core::Null? (value: null)] dynamic x) → dynamic
|
||||
return _in::unsafeCast<self::B::T?>(x);
|
||||
|
||||
+2
-2
@@ -12,13 +12,13 @@ class B<T extends core::Object? = dynamic> extends self::A<self::B::T%> {
|
||||
synthetic constructor •() → self::B<self::B::T%>
|
||||
: super self::A::•()
|
||||
;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method testT1([@vm.inferred-type.metadata=dart.core::_Smi (value: 42)] dynamic x) → dynamic
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i)->i] method testT1([@vm.inferred-type.metadata=dart.core::_Smi (value: 42)] dynamic x) → dynamic
|
||||
return _in::unsafeCast<self::B::T%>(x);
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method testT2negative([@vm.inferred-type.metadata=dart.core::Null? (value: null)] dynamic x) → dynamic
|
||||
return x as{ForNonNullableByDefault} self::B::T%;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method testT3([@vm.inferred-type.metadata=dart.core::Null? (value: null)] dynamic x) → dynamic
|
||||
return _in::unsafeCast<self::B::T%>(x);
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method testNullableT1([@vm.inferred-type.metadata=dart.core::_Smi (value: 42)] dynamic x) → dynamic
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(i)->i] method testNullableT1([@vm.inferred-type.metadata=dart.core::_Smi (value: 42)] dynamic x) → dynamic
|
||||
return _in::unsafeCast<self::B::T?>(x);
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method testNullableT2([@vm.inferred-type.metadata=dart.core::Null? (value: null)] dynamic x) → dynamic
|
||||
return _in::unsafeCast<self::B::T?>(x);
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
final bool kTrue = int.parse('1') == 1 ? true : false;
|
||||
final bool kFalse = int.parse('1') == 2 ? true : false;
|
||||
int get mint => 0xaabbccddaabbccdd;
|
||||
int get smiOrMint => kTrue ? 1 : mint;
|
||||
|
||||
abstract class BI1 {
|
||||
int get value;
|
||||
}
|
||||
|
||||
class BI1A implements BI1 {
|
||||
final int value;
|
||||
BI1A(this.value);
|
||||
}
|
||||
|
||||
class BI1B implements BI1 {
|
||||
int get value => null;
|
||||
}
|
||||
|
||||
abstract class BI2 {
|
||||
int get value;
|
||||
}
|
||||
|
||||
class BI2A implements BI2 {
|
||||
final int value;
|
||||
BI2A(this.value);
|
||||
}
|
||||
|
||||
class BI2B implements BI2 {
|
||||
int get value => smiOrMint;
|
||||
}
|
||||
|
||||
abstract class BI3 {
|
||||
int get value;
|
||||
set value(int value);
|
||||
}
|
||||
|
||||
class BI3A implements BI3 {
|
||||
int value;
|
||||
BI3A(this.value);
|
||||
}
|
||||
|
||||
class BI3B implements BI3 {
|
||||
int get value => smiOrMint;
|
||||
set value(int v) {}
|
||||
}
|
||||
|
||||
abstract class UBI {
|
||||
int value;
|
||||
}
|
||||
|
||||
class UBIA implements UBI {
|
||||
int value;
|
||||
UBIA(this.value);
|
||||
}
|
||||
|
||||
class UBIB implements UBI {
|
||||
int get value => smiOrMint;
|
||||
set value(int v) {}
|
||||
}
|
||||
|
||||
main() {
|
||||
// Getter return value needs to be boxed due to BI1B.value returning `null`.
|
||||
final bi1a = BI1A(smiOrMint);
|
||||
final bi1b = BI1B(); // getter returns null
|
||||
use((kTrue ? bi1a : bi1b).value);
|
||||
|
||||
// Getter return value needs to be boxed due to BI2A.value returning `null`.
|
||||
final bi2a = BI2A(null);
|
||||
final bi2b = BI2B(); // getter returns smiOrMint
|
||||
use((kTrue ? bi2a : bi2b).value);
|
||||
|
||||
// Getter return value needs to be boxed due to setter being called with
|
||||
// `null` value.
|
||||
final bi3a = BI3A(smiOrMint);
|
||||
final bi3b = BI3B(); // getter returns smiOrMint
|
||||
(kTrue ? bi3a : bi3b).value = null;
|
||||
use((kTrue ? bi3a : bi3b).value);
|
||||
|
||||
// Getter return value can be unboxed, both UBIA.value / UBIB.value return
|
||||
// non-nullable int.
|
||||
final ubia = UBIA(smiOrMint);
|
||||
final ubib = UBIB(); // getter returns smiOrMint
|
||||
use((kTrue ? ubia : ubib).value);
|
||||
}
|
||||
|
||||
void use(dynamic object) {}
|
||||
@@ -0,0 +1,91 @@
|
||||
library #lib;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
|
||||
abstract class BI1 extends core::Object {
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] abstract get value() → core::int*;
|
||||
}
|
||||
class BI1A extends core::Object implements self::BI1 {
|
||||
[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:1] final field core::int* value;
|
||||
[@vm.unboxing-info.metadata=(i)->b] constructor •([@vm.inferred-type.metadata=int] core::int* value) → self::BI1A*
|
||||
: self::BI1A::value = value, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class BI1B extends core::Object implements self::BI1 {
|
||||
synthetic constructor •() → self::BI1B*
|
||||
: super core::Object::•()
|
||||
;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] get value() → core::int*
|
||||
return null;
|
||||
}
|
||||
abstract class BI2 extends core::Object {
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] abstract get value() → core::int*;
|
||||
}
|
||||
class BI2A extends core::Object implements self::BI2 {
|
||||
[@vm.inferred-type.metadata=dart.core::Null? (value: null)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:3] final field core::int* value;
|
||||
constructor •([@vm.inferred-type.metadata=dart.core::Null? (value: null)] core::int* value) → self::BI2A*
|
||||
: self::BI2A::value = value, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class BI2B extends core::Object implements self::BI2 {
|
||||
synthetic constructor •() → self::BI2B*
|
||||
: super core::Object::•()
|
||||
;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] get value() → core::int*
|
||||
return [@vm.inferred-type.metadata=int] self::smiOrMint;
|
||||
}
|
||||
abstract class BI3 extends core::Object {
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] abstract get value() → core::int*;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] abstract set value(core::int* value) → void;
|
||||
}
|
||||
class BI3A extends core::Object implements self::BI3 {
|
||||
[@vm.inferred-type.metadata=int?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] field core::int* value;
|
||||
[@vm.unboxing-info.metadata=(i)->b] constructor •([@vm.inferred-type.metadata=int] core::int* value) → self::BI3A*
|
||||
: self::BI3A::value = value, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class BI3B extends core::Object implements self::BI3 {
|
||||
synthetic constructor •() → self::BI3B*
|
||||
: super core::Object::•()
|
||||
;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] get value() → core::int*
|
||||
return [@vm.inferred-type.metadata=int] self::smiOrMint;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] set value([@vm.inferred-type.metadata=dart.core::Null? (value: null)] core::int* v) → void {}
|
||||
}
|
||||
abstract class UBI extends core::Object {
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:7] [@vm.unboxing-info.metadata=()->i] abstract get value() → core::int*;
|
||||
}
|
||||
class UBIA extends core::Object implements self::UBI {
|
||||
[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8,getterSelectorId:7] [@vm.unboxing-info.metadata=()->i] field core::int* value;
|
||||
[@vm.unboxing-info.metadata=(i)->b] constructor •([@vm.inferred-type.metadata=int] core::int* value) → self::UBIA*
|
||||
: self::UBIA::value = value, super core::Object::•()
|
||||
;
|
||||
}
|
||||
class UBIB extends core::Object implements self::UBI {
|
||||
synthetic constructor •() → self::UBIB*
|
||||
: super core::Object::•()
|
||||
;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:7] [@vm.unboxing-info.metadata=()->i] get value() → core::int*
|
||||
return [@vm.inferred-type.metadata=int] self::smiOrMint;
|
||||
}
|
||||
[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kTrue = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.inferred-type.metadata=int] core::int::parse("1").{core::num::==}(1) ?{core::bool*} true : false;
|
||||
[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
|
||||
return -6144092014192636707;
|
||||
[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int*
|
||||
return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : [@vm.inferred-type.metadata=int] self::mint;
|
||||
static method main() → dynamic {
|
||||
final self::BI1A* bi1a = new self::BI1A::•([@vm.inferred-type.metadata=int] self::smiOrMint);
|
||||
final self::BI1B* bi1b = new self::BI1B::•();
|
||||
self::use([@vm.inferred-type.metadata=int?]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI1*} bi1a : bi1b).{self::BI1::value});
|
||||
final self::BI2A* bi2a = new self::BI2A::•(null);
|
||||
final self::BI2B* bi2b = new self::BI2B::•();
|
||||
self::use([@vm.inferred-type.metadata=int?]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI2*} bi2a : bi2b).{self::BI2::value});
|
||||
final self::BI3A* bi3a = new self::BI3A::•([@vm.inferred-type.metadata=int] self::smiOrMint);
|
||||
final self::BI3B* bi3b = new self::BI3B::•();
|
||||
([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI3*} bi3a : bi3b).{self::BI3::value} = null;
|
||||
self::use([@vm.inferred-type.metadata=int?]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI3*} bi3a : bi3b).{self::BI3::value});
|
||||
final self::UBIA* ubia = new self::UBIA::•([@vm.inferred-type.metadata=int] self::smiOrMint);
|
||||
final self::UBIB* ubib = new self::UBIB::•();
|
||||
self::use([@vm.inferred-type.metadata=int]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::UBI*} ubia : ubib).{self::UBI::value});
|
||||
}
|
||||
static method use([@vm.inferred-type.metadata=int?] dynamic object) → void {}
|
||||
+5
-5
@@ -8,9 +8,9 @@ class X extends core::Object {
|
||||
;
|
||||
}
|
||||
class A extends core::Object {
|
||||
[@vm.inferred-type.metadata=dart.core::_Smi] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] field dynamic unboxedSmi;
|
||||
[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] field dynamic unboxedInt;
|
||||
[@vm.inferred-type.metadata=dart.core::_Double] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] field dynamic unboxedDouble;
|
||||
[@vm.inferred-type.metadata=dart.core::_Smi] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i)->i] field dynamic unboxedSmi;
|
||||
[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(i)->i] field dynamic unboxedInt;
|
||||
[@vm.inferred-type.metadata=dart.core::_Double] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(d)->d] field dynamic unboxedDouble;
|
||||
[@vm.inferred-type.metadata=int?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] field dynamic boxedNullableInt;
|
||||
[@vm.inferred-type.metadata=dart.core::_Double?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] field dynamic boxedNullableDouble;
|
||||
[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] field dynamic boxedNonNullableIntOrDouble;
|
||||
@@ -23,9 +23,9 @@ class A extends core::Object {
|
||||
}
|
||||
[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kTrue = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.inferred-type.metadata=int] core::int::parse("1").{core::num::==}(1) ?{core::bool*} true : false;
|
||||
[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kFalse = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.inferred-type.metadata=int] core::int::parse("1").{core::num::==}(2) ?{core::bool*} true : false;
|
||||
static get mint() → core::int*
|
||||
[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
|
||||
return -6144092014192636707;
|
||||
static get smiOrMint() → core::int*
|
||||
[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int*
|
||||
return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : [@vm.inferred-type.metadata=int] self::mint;
|
||||
static method main() → dynamic {
|
||||
final self::A* a = new self::A::•([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null, new self::X::•());
|
||||
|
||||
+1
-1
@@ -91,7 +91,7 @@ class SubImpl3 extends self::BaseImpl2 implements self::Interface {
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] method returnBoxedX([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
|
||||
return new self::X::•();
|
||||
}
|
||||
static get mint() → core::int*
|
||||
[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
|
||||
return -6144092014192636707;
|
||||
static method main() → dynamic {
|
||||
final core::List<core::Object*>* values = <core::Object*>[new self::Impl1::•(), new self::BaseImpl2::•(), new self::SubImpl3::•()];
|
||||
|
||||
+1
-1
@@ -91,7 +91,7 @@ class SubImpl3 extends self::BaseImpl2 implements self::Interface {
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] method returnBoxedX(self::X* ignored) → dynamic
|
||||
return new self::X::•();
|
||||
}
|
||||
static get mint() → core::int*
|
||||
[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
|
||||
return -6144092014192636707;
|
||||
static method main() → dynamic {
|
||||
final core::List<core::Object*>* values = <core::Object*>[new self::Impl1::•(), new self::BaseImpl2::•(), new self::SubImpl3::•()];
|
||||
|
||||
+2
-2
@@ -9,9 +9,9 @@ class X extends core::Object {
|
||||
}
|
||||
[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kTrue = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.inferred-type.metadata=int] core::int::parse("1").{core::num::==}(1) ?{core::bool*} true : false;
|
||||
[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kFalse = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.inferred-type.metadata=int] core::int::parse("1").{core::num::==}(2) ?{core::bool*} true : false;
|
||||
static get mint() → core::int*
|
||||
[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
|
||||
return -6144092014192636707;
|
||||
static get smiOrMint() → core::int*
|
||||
[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int*
|
||||
return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : [@vm.inferred-type.metadata=int] self::mint;
|
||||
[@vm.unboxing-info.metadata=(i,i,d,b,b,b,b,b,b)->b]static method takePositional([@vm.inferred-type.metadata=dart.core::_Smi] core::int* unboxedSmi, [@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=!] dynamic boxedIntOrDouble, dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {}
|
||||
static method takeOptional([@vm.inferred-type.metadata=dart.core::_Smi] core::int* unboxedSmi, [@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=!] dynamic boxedIntOrDouble, dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {}
|
||||
|
||||
+2
-2
@@ -9,9 +9,9 @@ class X extends core::Object {
|
||||
}
|
||||
[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kTrue = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.inferred-type.metadata=int] core::int::parse("1").{core::num::==}(1) ?{core::bool*} true : false;
|
||||
[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kFalse = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.inferred-type.metadata=int] core::int::parse("1").{core::num::==}(2) ?{core::bool*} true : false;
|
||||
static get mint() → core::int*
|
||||
[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
|
||||
return -6144092014192636707;
|
||||
static get smiOrMint() → core::int*
|
||||
[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int*
|
||||
return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : [@vm.inferred-type.metadata=int] self::mint;
|
||||
static method takePositional(core::int* unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {}
|
||||
static method takeOptional([@vm.inferred-type.metadata=dart.core::_Smi] core::int* unboxedSmi, [@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=!] dynamic boxedIntOrDouble, dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {}
|
||||
|
||||
+3
-3
@@ -26,17 +26,17 @@ class D extends core::Object implements self::C<core::int*> {
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3] set bar(generic-covariant-impl core::int* value) → void;
|
||||
}
|
||||
abstract class E extends core::Object {
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4] abstract get bar() → core::int*;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i] abstract get bar() → core::int*;
|
||||
}
|
||||
class F extends core::Object implements self::E {
|
||||
synthetic constructor •() → self::F*
|
||||
: super core::Object::•()
|
||||
;
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4] get bar() → core::int*
|
||||
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i] get bar() → core::int*
|
||||
return 42;
|
||||
}
|
||||
class G extends core::Object /*hasConstConstructor*/ {
|
||||
[@vm.inferred-type.metadata=dart.core::_Smi] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] final field core::int* bazz;
|
||||
[@vm.inferred-type.metadata=dart.core::_Smi] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=()->i] final field core::int* bazz;
|
||||
}
|
||||
abstract class H extends core::Object {
|
||||
synthetic constructor •() → self::H*
|
||||
|
||||
@@ -6,17 +6,12 @@ import 'dart:_internal' show VMInternalsForTesting;
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
import 'unboxed_parameter_helper.dart';
|
||||
|
||||
// The VM class finalizer ensures that we only unbox fields which can be
|
||||
// represented in the unboxed field bitmap in the target architecture (even when
|
||||
// cross-compiling from 64-bit to 32-bit), see `Class::CalculateFieldOffsets()`.
|
||||
|
||||
// Make an integer that would look like an object pointer (irrespective of
|
||||
// we compile to 32-bit or 64-bit and whether we use little or big endian
|
||||
// encoding of the integer).
|
||||
int get integerFieldValue =>
|
||||
int.parse('1') == 1 ? constIntegerFieldValue : 0x8000900180009001;
|
||||
const int constIntegerFieldValue = 0x8000000180000001;
|
||||
|
||||
int i = 0;
|
||||
final Object objectFieldValue = Foo('i${i++}');
|
||||
|
||||
|
||||
@@ -11,3 +11,10 @@ double getDoubleWithHeapObjectTag() {
|
||||
final double v = bd.getFloat64(0, Endian.host);
|
||||
return v;
|
||||
}
|
||||
|
||||
// Make an integer that would look like an object pointer (irrespective of
|
||||
// we compile to 32-bit or 64-bit and whether we use little or big endian
|
||||
// encoding of the integer).
|
||||
int get integerFieldValue =>
|
||||
int.parse('1') == 1 ? constIntegerFieldValue : 0x8000900180009001;
|
||||
const int constIntegerFieldValue = 0x8000000180000001;
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
import 'unboxed_parameter_helper.dart';
|
||||
|
||||
abstract class I {
|
||||
int get value;
|
||||
int getValue();
|
||||
}
|
||||
|
||||
class Foo implements I {
|
||||
int value;
|
||||
Foo(this.value);
|
||||
int getValue() => value;
|
||||
}
|
||||
|
||||
class Bar implements I {
|
||||
int get value => integerFieldValue;
|
||||
int getValue() => value;
|
||||
}
|
||||
|
||||
final objects = <dynamic>[Foo(integerFieldValue), Bar()];
|
||||
final tearoffs = <dynamic>[Foo(integerFieldValue).getValue, Bar().getValue];
|
||||
|
||||
main() {
|
||||
// Dynamic accesses to getter, method and tear-off
|
||||
Expect.equals(objects[0].value, integerFieldValue);
|
||||
Expect.equals(objects[0].getValue(), integerFieldValue);
|
||||
Expect.equals(objects[1].value, integerFieldValue);
|
||||
Expect.equals(objects[1].getValue(), integerFieldValue);
|
||||
Expect.equals(tearoffs[0](), integerFieldValue);
|
||||
Expect.equals(tearoffs[1](), integerFieldValue);
|
||||
|
||||
// Interface-based accesses to getter, method and tear-off
|
||||
final Foo foo = objects[0] as Foo;
|
||||
final int Function() fooGetValue = foo.getValue;
|
||||
Expect.equals(foo.value, integerFieldValue);
|
||||
Expect.equals(foo.getValue(), integerFieldValue);
|
||||
Expect.equals(fooGetValue(), integerFieldValue);
|
||||
|
||||
final Bar bar = objects[1] as Bar;
|
||||
final int Function() barGetValue = bar.getValue;
|
||||
Expect.equals(bar.value, integerFieldValue);
|
||||
Expect.equals(bar.getValue(), integerFieldValue);
|
||||
Expect.equals(barGetValue(), integerFieldValue);
|
||||
}
|
||||
@@ -6,17 +6,12 @@ import 'dart:_internal' show VMInternalsForTesting;
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
import 'unboxed_parameter_helper.dart';
|
||||
|
||||
// The VM class finalizer ensures that we only unbox fields which can be
|
||||
// represented in the unboxed field bitmap in the target architecture (even when
|
||||
// cross-compiling from 64-bit to 32-bit), see `Class::CalculateFieldOffsets()`.
|
||||
|
||||
// Make an integer that would look like an object pointer (irrespective of
|
||||
// we compile to 32-bit or 64-bit and whether we use little or big endian
|
||||
// encoding of the integer).
|
||||
int get integerFieldValue =>
|
||||
int.parse('1') == 1 ? constIntegerFieldValue : 0x8000900180009001;
|
||||
const int constIntegerFieldValue = 0x8000000180000001;
|
||||
|
||||
int i = 0;
|
||||
final Object objectFieldValue = Foo('i${i++}');
|
||||
|
||||
|
||||
@@ -11,3 +11,10 @@ double getDoubleWithHeapObjectTag() {
|
||||
final double v = bd.getFloat64(0, Endian.host);
|
||||
return v;
|
||||
}
|
||||
|
||||
// Make an integer that would look like an object pointer (irrespective of
|
||||
// we compile to 32-bit or 64-bit and whether we use little or big endian
|
||||
// encoding of the integer).
|
||||
int get integerFieldValue =>
|
||||
int.parse('1') == 1 ? constIntegerFieldValue : 0x8000900180009001;
|
||||
const int constIntegerFieldValue = 0x8000000180000001;
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
import 'unboxed_parameter_helper.dart';
|
||||
|
||||
abstract class I {
|
||||
int get value;
|
||||
int getValue();
|
||||
}
|
||||
|
||||
class Foo implements I {
|
||||
int value;
|
||||
Foo(this.value);
|
||||
int getValue() => value;
|
||||
}
|
||||
|
||||
class Bar implements I {
|
||||
int get value => integerFieldValue;
|
||||
int getValue() => value;
|
||||
}
|
||||
|
||||
final objects = <dynamic>[Foo(integerFieldValue), Bar()];
|
||||
final tearoffs = <dynamic>[Foo(integerFieldValue).getValue, Bar().getValue];
|
||||
|
||||
main() {
|
||||
// Dynamic accesses to getter, method and tear-off
|
||||
Expect.equals(objects[0].value, integerFieldValue);
|
||||
Expect.equals(objects[0].getValue(), integerFieldValue);
|
||||
Expect.equals(objects[1].value, integerFieldValue);
|
||||
Expect.equals(objects[1].getValue(), integerFieldValue);
|
||||
Expect.equals(tearoffs[0](), integerFieldValue);
|
||||
Expect.equals(tearoffs[1](), integerFieldValue);
|
||||
|
||||
// Interface-based accesses to getter, method and tear-off
|
||||
final Foo foo = objects[0] as Foo;
|
||||
final int Function() fooGetValue = foo.getValue;
|
||||
Expect.equals(foo.value, integerFieldValue);
|
||||
Expect.equals(foo.getValue(), integerFieldValue);
|
||||
Expect.equals(fooGetValue(), integerFieldValue);
|
||||
|
||||
final Bar bar = objects[1] as Bar;
|
||||
final int Function() barGetValue = bar.getValue;
|
||||
Expect.equals(bar.value, integerFieldValue);
|
||||
Expect.equals(bar.getValue(), integerFieldValue);
|
||||
Expect.equals(barGetValue(), integerFieldValue);
|
||||
}
|
||||
@@ -1028,6 +1028,14 @@ bool Precompiler::MustRetainFunction(const Function& function) {
|
||||
if (name.Equals(Symbols::_ClosureCall())) return true;
|
||||
}
|
||||
|
||||
// We have to retain functions which can be a target of a SwitchableCall
|
||||
// at AOT runtime, since the AOT runtime needs to be able to find the
|
||||
// function object in the class.
|
||||
if (function.NeedsMonomorphicCheckedEntry(Z) ||
|
||||
Function::IsDynamicInvocationForwarderName(function.name())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -2559,17 +2559,18 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfFieldAccessor(
|
||||
// type and then invokes original setter we simply generate the type check
|
||||
// and inlined field store. Scope builder takes care of setting correct
|
||||
// type check mode in this case.
|
||||
const bool is_setter = function.IsDynamicInvocationForwarder() ||
|
||||
function.IsImplicitSetterFunction();
|
||||
const bool is_method = !function.IsStaticFunction();
|
||||
const auto& target = Function::Handle(
|
||||
Z, function.IsDynamicInvocationForwarder() ? function.ForwardingTarget()
|
||||
: function.raw());
|
||||
ASSERT(target.IsImplicitGetterOrSetter());
|
||||
|
||||
Field& field = Field::ZoneHandle(Z);
|
||||
if (function.IsDynamicInvocationForwarder()) {
|
||||
Function& target = Function::Handle(function.ForwardingTarget());
|
||||
field = target.accessor_field();
|
||||
} else {
|
||||
field = function.accessor_field();
|
||||
}
|
||||
const bool is_method = !function.IsStaticFunction();
|
||||
const bool is_setter = target.IsImplicitSetterFunction();
|
||||
const bool is_getter = target.IsImplicitGetterFunction() ||
|
||||
target.IsImplicitStaticGetterFunction();
|
||||
ASSERT(is_setter || is_getter);
|
||||
|
||||
const auto& field = Field::ZoneHandle(Z, target.accessor_field());
|
||||
|
||||
graph_entry_ =
|
||||
new (Z) GraphEntryInstr(*parsed_function_, Compiler::kNoOSRDeoptId);
|
||||
@@ -2579,18 +2580,20 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfFieldAccessor(
|
||||
|
||||
Fragment body(normal_entry);
|
||||
if (is_setter) {
|
||||
LocalVariable* setter_value =
|
||||
auto const setter_value =
|
||||
parsed_function_->ParameterVariable(is_method ? 1 : 0);
|
||||
|
||||
// We only expect to generate a dynamic invocation forwarder if
|
||||
// the value needs type check.
|
||||
ASSERT(!function.IsDynamicInvocationForwarder() ||
|
||||
setter_value->needs_type_check());
|
||||
if (is_method) {
|
||||
body += LoadLocal(parsed_function_->ParameterVariable(0));
|
||||
}
|
||||
body += LoadLocal(setter_value);
|
||||
if (setter_value->needs_type_check()) {
|
||||
|
||||
// The dyn:* forwarder has to check the parameters that the
|
||||
// actual target will not check.
|
||||
// Though here we manually inline the target, so the dyn:* forwarder has to
|
||||
// check all parameters.
|
||||
const bool needs_type_check = function.IsDynamicInvocationForwarder() ||
|
||||
setter_value->needs_type_check();
|
||||
if (needs_type_check) {
|
||||
body += CheckAssignable(setter_value->type(), setter_value->name(),
|
||||
AssertAssignableInstr::kParameterCheck);
|
||||
}
|
||||
@@ -2612,7 +2615,7 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfFieldAccessor(
|
||||
}
|
||||
}
|
||||
body += NullConstant();
|
||||
} else if (is_method) {
|
||||
} else if (is_getter && is_method) {
|
||||
ASSERT(!field.needs_load_guard()
|
||||
NOT_IN_PRODUCT(|| I->HasAttemptedReload()));
|
||||
body += LoadLocal(parsed_function_->ParameterVariable(0));
|
||||
@@ -2661,15 +2664,15 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfDynamicInvocationForwarder(
|
||||
const Function& function) {
|
||||
auto& name = String::Handle(Z, function.name());
|
||||
name = Function::DemangleDynamicInvocationForwarderName(name);
|
||||
const auto& owner = Class::Handle(Z, function.Owner());
|
||||
const auto& target =
|
||||
Function::ZoneHandle(Z, owner.LookupDynamicFunction(name));
|
||||
const auto& target = Function::ZoneHandle(Z, function.ForwardingTarget());
|
||||
ASSERT(!target.IsNull());
|
||||
ASSERT(!target.IsImplicitGetterFunction());
|
||||
|
||||
if (target.IsImplicitSetterFunction()) {
|
||||
if (target.IsImplicitSetterFunction() || target.IsImplicitGetterFunction()) {
|
||||
return BuildGraphOfFieldAccessor(function);
|
||||
}
|
||||
if (target.IsMethodExtractor()) {
|
||||
return BuildGraphOfMethodExtractor(target);
|
||||
}
|
||||
|
||||
graph_entry_ = new (Z) GraphEntryInstr(*parsed_function_, osr_id_);
|
||||
|
||||
|
||||
@@ -3417,11 +3417,35 @@ static void SetupUnboxingInfoOfParameter(const Function& function,
|
||||
}
|
||||
}
|
||||
|
||||
static void SetupUnboxingInfoOfReturnValue(
|
||||
const Function& function,
|
||||
const UnboxingInfoMetadata* metadata) {
|
||||
switch (metadata->return_info) {
|
||||
case UnboxingInfoMetadata::kUnboxedIntCandidate:
|
||||
if (FlowGraphCompiler::SupportsUnboxedInt64()) {
|
||||
function.set_unboxed_integer_return();
|
||||
}
|
||||
break;
|
||||
case UnboxingInfoMetadata::kUnboxedDoubleCandidate:
|
||||
if (FlowGraphCompiler::SupportsUnboxedDoubles()) {
|
||||
function.set_unboxed_double_return();
|
||||
}
|
||||
break;
|
||||
case UnboxingInfoMetadata::kUnboxingCandidate:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
case UnboxingInfoMetadata::kBoxed:
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TypeTranslator::SetupUnboxingInfoMetadata(const Function& function,
|
||||
intptr_t library_kernel_offset) {
|
||||
const intptr_t kernel_offset =
|
||||
function.kernel_offset() + library_kernel_offset;
|
||||
|
||||
const auto unboxing_info =
|
||||
unboxing_info_metadata_helper_.GetUnboxingInfoMetadata(kernel_offset);
|
||||
|
||||
@@ -3432,26 +3456,29 @@ void TypeTranslator::SetupUnboxingInfoMetadata(const Function& function,
|
||||
for (intptr_t i = 0; i < unboxing_info->unboxed_args_info.length(); i++) {
|
||||
SetupUnboxingInfoOfParameter(function, i, unboxing_info);
|
||||
}
|
||||
SetupUnboxingInfoOfReturnValue(function, unboxing_info);
|
||||
}
|
||||
}
|
||||
|
||||
switch (unboxing_info->return_info) {
|
||||
case UnboxingInfoMetadata::kUnboxedIntCandidate:
|
||||
if (FlowGraphCompiler::SupportsUnboxedInt64()) {
|
||||
function.set_unboxed_integer_return();
|
||||
}
|
||||
break;
|
||||
case UnboxingInfoMetadata::kUnboxedDoubleCandidate:
|
||||
if (FlowGraphCompiler::SupportsUnboxedDoubles()) {
|
||||
function.set_unboxed_double_return();
|
||||
}
|
||||
break;
|
||||
case UnboxingInfoMetadata::kUnboxingCandidate:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
case UnboxingInfoMetadata::kBoxed:
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
void TypeTranslator::SetupUnboxingInfoMetadataForFieldAccessors(
|
||||
const Function& field_accessor,
|
||||
intptr_t library_kernel_offset) {
|
||||
const intptr_t kernel_offset =
|
||||
field_accessor.kernel_offset() + library_kernel_offset;
|
||||
const auto unboxing_info =
|
||||
unboxing_info_metadata_helper_.GetUnboxingInfoMetadata(kernel_offset);
|
||||
|
||||
// TODO(dartbug.com/32292): accept unboxed parameters and return value
|
||||
// when FLAG_use_table_dispatch == false.
|
||||
if (FLAG_precompiled_mode && unboxing_info != nullptr &&
|
||||
FLAG_use_table_dispatch && FLAG_use_bare_instructions) {
|
||||
if (field_accessor.IsImplicitSetterFunction()) {
|
||||
for (intptr_t i = 0; i < unboxing_info->unboxed_args_info.length(); i++) {
|
||||
SetupUnboxingInfoOfParameter(field_accessor, i, unboxing_info);
|
||||
}
|
||||
} else {
|
||||
ASSERT(field_accessor.IsImplicitGetterFunction());
|
||||
SetupUnboxingInfoOfReturnValue(field_accessor, unboxing_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1469,6 +1469,9 @@ class TypeTranslator {
|
||||
private:
|
||||
void SetupUnboxingInfoMetadata(const Function& function,
|
||||
intptr_t library_kernel_offset);
|
||||
void SetupUnboxingInfoMetadataForFieldAccessors(
|
||||
const Function& field_accessor,
|
||||
intptr_t library_kernel_offset);
|
||||
|
||||
void BuildTypeInternal();
|
||||
void BuildInterfaceType(bool simple);
|
||||
|
||||
@@ -346,13 +346,13 @@ ScopeBuildingResult* ScopeBuilder::BuildScopes() {
|
||||
break;
|
||||
}
|
||||
case FunctionLayout::kDynamicInvocationForwarder: {
|
||||
const String& name = String::Handle(Z, function.name());
|
||||
ASSERT(Function::IsDynamicInvocationForwarderName(name));
|
||||
|
||||
const auto& target = Function::ZoneHandle(Z, function.ForwardingTarget());
|
||||
ASSERT(!target.IsNull());
|
||||
|
||||
if (helper_.PeekTag() == kField) {
|
||||
#ifdef DEBUG
|
||||
String& name = String::Handle(Z, function.name());
|
||||
ASSERT(Function::IsDynamicInvocationForwarderName(name));
|
||||
name = Function::DemangleDynamicInvocationForwarderName(name);
|
||||
ASSERT(Field::IsSetterName(name));
|
||||
#endif
|
||||
// Create [this] variable.
|
||||
const Class& klass = Class::Handle(Z, function.Owner());
|
||||
parsed_function_->set_receiver_var(
|
||||
@@ -361,29 +361,36 @@ ScopeBuildingResult* ScopeBuilder::BuildScopes() {
|
||||
scope_->InsertParameterAt(0, parsed_function_->receiver_var());
|
||||
|
||||
// Create setter value variable.
|
||||
result_->setter_value = MakeVariable(
|
||||
TokenPosition::kNoSource, TokenPosition::kNoSource,
|
||||
Symbols::Value(),
|
||||
AbstractType::ZoneHandle(Z, function.ParameterTypeAt(1)));
|
||||
scope_->InsertParameterAt(1, result_->setter_value);
|
||||
} else {
|
||||
helper_.ReadUntilFunctionNode();
|
||||
function_node_helper.ReadUntilExcluding(
|
||||
FunctionNodeHelper::kPositionalParameters);
|
||||
|
||||
// Create [this] variable.
|
||||
intptr_t pos = 0;
|
||||
Class& klass = Class::Handle(Z, function.Owner());
|
||||
parsed_function_->set_receiver_var(
|
||||
MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
|
||||
Symbols::This(), H.GetDeclarationType(klass)));
|
||||
scope_->InsertParameterAt(pos++, parsed_function_->receiver_var());
|
||||
|
||||
// Create all positional and named parameters.
|
||||
AddPositionalAndNamedParameters(
|
||||
pos, kTypeCheckEverythingNotCheckedInNonDynamicallyInvokedMethod,
|
||||
attrs);
|
||||
if (target.IsImplicitSetterFunction()) {
|
||||
result_->setter_value = MakeVariable(
|
||||
TokenPosition::kNoSource, TokenPosition::kNoSource,
|
||||
Symbols::Value(),
|
||||
AbstractType::ZoneHandle(Z, function.ParameterTypeAt(1)));
|
||||
scope_->InsertParameterAt(1, result_->setter_value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// We do not create dyn:* forwarders for method extractors, since those
|
||||
// can never return unboxed values (they return a closure).
|
||||
ASSERT(!target.IsMethodExtractor());
|
||||
|
||||
helper_.ReadUntilFunctionNode();
|
||||
function_node_helper.ReadUntilExcluding(
|
||||
FunctionNodeHelper::kPositionalParameters);
|
||||
|
||||
// Create [this] variable.
|
||||
intptr_t pos = 0;
|
||||
Class& klass = Class::Handle(Z, function.Owner());
|
||||
parsed_function_->set_receiver_var(
|
||||
MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
|
||||
Symbols::This(), H.GetDeclarationType(klass)));
|
||||
scope_->InsertParameterAt(pos++, parsed_function_->receiver_var());
|
||||
|
||||
// Create all positional and named parameters.
|
||||
AddPositionalAndNamedParameters(
|
||||
pos, kTypeCheckEverythingNotCheckedInNonDynamicallyInvokedMethod,
|
||||
attrs);
|
||||
break;
|
||||
}
|
||||
case FunctionLayout::kMethodExtractor: {
|
||||
|
||||
+32
-8
@@ -718,18 +718,42 @@ void ReadParameterCovariance(const Function& function,
|
||||
bool NeedsDynamicInvocationForwarder(const Function& function) {
|
||||
Zone* zone = Thread::Current()->zone();
|
||||
|
||||
// Right now closures do not need a dyn:* forwarder.
|
||||
// See https://github.com/dart-lang/sdk/issues/40813
|
||||
if (function.IsClosureFunction()) return false;
|
||||
|
||||
// Method extractors have no parameters to check and return value is a closure
|
||||
// and therefore not an unboxed primitive type.
|
||||
if (function.IsMethodExtractor()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Invoke field dispatchers are dynamically generated, will invoke a getter to
|
||||
// obtain the field value and then invoke ".call()" on the result.
|
||||
// Those dynamically generated dispathers don't have proper kernel metadata
|
||||
// associated with them - we can therefore not query if there are dynamic
|
||||
// calls to them or not and are therefore conservative.
|
||||
if (function.IsInvokeFieldDispatcher()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// The dyn:* forwarders perform unboxing of parameters before calling the
|
||||
// actual target (which accepts unboxed parameters) and boxes return values
|
||||
// of the return value.
|
||||
if (function.HasUnboxedParameters() || function.HasUnboxedReturnValue()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// There are no parameters to type check for getters and if the return value
|
||||
// is boxed, then the dyn:* forwarder is not needed.
|
||||
if (function.IsImplicitGetterFunction()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Covariant parameters (both explicitly covariant and generic-covariant-impl)
|
||||
// are checked in the body of a function and therefore don't need checks in a
|
||||
// dynamic invocation forwarder. So dynamic invocation forwarder is only
|
||||
// needed if there are non-covariant parameters of non-top type.
|
||||
|
||||
// TODO(dartbug.com/40876): Implement dynamic invocation forwarders for
|
||||
// getters.
|
||||
if (function.IsImplicitGetterFunction() ||
|
||||
function.IsImplicitClosureFunction() || function.IsMethodExtractor()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (function.IsImplicitSetterFunction()) {
|
||||
const auto& field = Field::Handle(zone, function.accessor_field());
|
||||
return !(field.is_covariant() || field.is_generic_covariant_impl());
|
||||
|
||||
@@ -2244,6 +2244,7 @@ void KernelLoader::GenerateFieldAccessors(const Class& klass,
|
||||
getter.set_accessor_field(field);
|
||||
getter.set_is_extension_member(field.is_extension_member());
|
||||
H.SetupFieldAccessorFunction(klass, getter, field_type);
|
||||
T.SetupUnboxingInfoMetadataForFieldAccessors(getter, library_kernel_offset_);
|
||||
|
||||
if (field.NeedsSetter()) {
|
||||
// Only static fields can be const.
|
||||
@@ -2265,6 +2266,8 @@ void KernelLoader::GenerateFieldAccessors(const Class& klass,
|
||||
setter.set_accessor_field(field);
|
||||
setter.set_is_extension_member(field.is_extension_member());
|
||||
H.SetupFieldAccessorFunction(klass, setter, field_type);
|
||||
T.SetupUnboxingInfoMetadataForFieldAccessors(getter,
|
||||
library_kernel_offset_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+43
-5
@@ -3724,10 +3724,13 @@ FunctionPtr Function::GetDynamicInvocationForwarder(
|
||||
const String& mangled_name,
|
||||
bool allow_add /* = true */) const {
|
||||
ASSERT(IsDynamicInvocationForwarderName(mangled_name));
|
||||
const Class& owner = Class::Handle(Owner());
|
||||
Function& result = Function::Handle(owner.GetInvocationDispatcher(
|
||||
mangled_name, Array::null_array(),
|
||||
FunctionLayout::kDynamicInvocationForwarder, /*create_if_absent=*/false));
|
||||
auto zone = Thread::Current()->zone();
|
||||
const Class& owner = Class::Handle(zone, Owner());
|
||||
Function& result = Function::Handle(
|
||||
zone,
|
||||
owner.GetInvocationDispatcher(mangled_name, Array::null_array(),
|
||||
FunctionLayout::kDynamicInvocationForwarder,
|
||||
/*create_if_absent=*/false));
|
||||
|
||||
if (!result.IsNull()) {
|
||||
return result.raw();
|
||||
@@ -9122,7 +9125,15 @@ void Function::SetKernelDataAndScript(const Script& script,
|
||||
ScriptPtr Function::script() const {
|
||||
// NOTE(turnidge): If you update this function, you probably want to
|
||||
// update Class::PatchFieldsAndFunctions() at the same time.
|
||||
Object& data = Object::Handle(raw_ptr()->data_);
|
||||
const Object& data = Object::Handle(raw_ptr()->data_);
|
||||
if (IsDynamicInvocationForwarder()) {
|
||||
const auto& forwarding_target = Function::Handle(ForwardingTarget());
|
||||
return forwarding_target.script();
|
||||
}
|
||||
if (IsImplicitGetterOrSetter()) {
|
||||
const auto& field = Field::Handle(accessor_field());
|
||||
return field.Script();
|
||||
}
|
||||
if (data.IsArray()) {
|
||||
Object& script = Object::Handle(Array::Cast(data).At(0));
|
||||
if (script.IsScript()) {
|
||||
@@ -9590,12 +9601,39 @@ bool Function::NeedsMonomorphicCheckedEntry(Zone* zone) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// All dyn:* forwarders are called via SwitchableCalls and all except the ones
|
||||
// with `PrologueNeedsArgumentsDescriptor()` transition into monomorphic
|
||||
// state.
|
||||
if (Function::IsDynamicInvocationForwarderName(name())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If table dispatch is disabled, all instance calls use switchable calls.
|
||||
if (!(FLAG_precompiled_mode && FLAG_use_bare_instructions &&
|
||||
FLAG_use_table_dispatch)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Only if there are dynamic callers and if we didn't create a dyn:* forwarder
|
||||
// for it do we need the monomorphic checked entry.
|
||||
return HasDynamicCallers(zone) &&
|
||||
!kernel::NeedsDynamicInvocationForwarder(*this);
|
||||
#else
|
||||
UNREACHABLE();
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Function::HasDynamicCallers(Zone* zone) const {
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
// Issue(dartbug.com/42719):
|
||||
// Right now the metadata of _Closure.call says there are no dynamic callers -
|
||||
// even though there can be. To be conservative we return true.
|
||||
if ((name() == Symbols::GetCall().raw() || name() == Symbols::Call().raw()) &&
|
||||
Class::IsClosureClass(Owner())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Use the results of TFA to determine whether this function is ever
|
||||
// called dynamically, i.e. using switchable calls.
|
||||
kernel::ProcedureAttributesMetadata metadata;
|
||||
|
||||
@@ -2756,6 +2756,10 @@ class Function : public Object {
|
||||
void set_accessor_field(const Field& value) const;
|
||||
FieldPtr accessor_field() const;
|
||||
|
||||
bool IsRegularFunction() const {
|
||||
return kind() == FunctionLayout::kRegularFunction;
|
||||
}
|
||||
|
||||
bool IsMethodExtractor() const {
|
||||
return kind() == FunctionLayout::kMethodExtractor;
|
||||
}
|
||||
@@ -2911,6 +2915,7 @@ class Function : public Object {
|
||||
}
|
||||
|
||||
bool NeedsMonomorphicCheckedEntry(Zone* zone) const;
|
||||
bool HasDynamicCallers(Zone* zone) const;
|
||||
bool PrologueNeedsArgumentsDescriptor() const;
|
||||
|
||||
bool MayHaveUncheckedEntryPoint() const;
|
||||
@@ -3307,6 +3312,15 @@ class Function : public Object {
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||
}
|
||||
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
bool HasUnboxedParameters() const {
|
||||
return raw_ptr()->unboxed_parameters_info_.HasUnboxedParameters();
|
||||
}
|
||||
bool HasUnboxedReturnValue() const {
|
||||
return raw_ptr()->unboxed_parameters_info_.HasUnboxedReturnValue();
|
||||
}
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
// Returns true if the type of this function is a subtype of the type of
|
||||
// the other function.
|
||||
bool IsSubtypeOf(const Function& other, Heap::Space space) const;
|
||||
@@ -3335,6 +3349,12 @@ class Function : public Object {
|
||||
return kind() == FunctionLayout::kImplicitGetter;
|
||||
}
|
||||
|
||||
// Returns true if this function represents an implicit static getter
|
||||
// function.
|
||||
bool IsImplicitStaticGetterFunction() const {
|
||||
return kind() == FunctionLayout::kImplicitStaticGetter;
|
||||
}
|
||||
|
||||
// Returns true if this function represents an explicit setter function.
|
||||
bool IsSetterFunction() const {
|
||||
return kind() == FunctionLayout::kSetterFunction;
|
||||
|
||||
+19
-11
@@ -931,6 +931,7 @@ class FunctionLayout : public ObjectLayout {
|
||||
class UnboxedParameterBitmap {
|
||||
public:
|
||||
static constexpr intptr_t kBitsPerParameter = 2;
|
||||
static constexpr intptr_t kParameterBitmask = (1 << kBitsPerParameter) - 1;
|
||||
static constexpr intptr_t kCapacity =
|
||||
(kBitsPerByte * sizeof(uint64_t)) / kBitsPerParameter;
|
||||
|
||||
@@ -943,37 +944,44 @@ class FunctionLayout : public ObjectLayout {
|
||||
if (position >= kCapacity) {
|
||||
return false;
|
||||
}
|
||||
ASSERT(Utils::TestBit(bitmap_, 2 * position) ||
|
||||
!Utils::TestBit(bitmap_, 2 * position + 1));
|
||||
return Utils::TestBit(bitmap_, 2 * position);
|
||||
ASSERT(Utils::TestBit(bitmap_, kBitsPerParameter * position) ||
|
||||
!Utils::TestBit(bitmap_, kBitsPerParameter * position + 1));
|
||||
return Utils::TestBit(bitmap_, kBitsPerParameter * position);
|
||||
}
|
||||
DART_FORCE_INLINE bool IsUnboxedInteger(intptr_t position) const {
|
||||
if (position >= kCapacity) {
|
||||
return false;
|
||||
}
|
||||
return Utils::TestBit(bitmap_, 2 * position) &&
|
||||
!Utils::TestBit(bitmap_, 2 * position + 1);
|
||||
return Utils::TestBit(bitmap_, kBitsPerParameter * position) &&
|
||||
!Utils::TestBit(bitmap_, kBitsPerParameter * position + 1);
|
||||
}
|
||||
DART_FORCE_INLINE bool IsUnboxedDouble(intptr_t position) const {
|
||||
if (position >= kCapacity) {
|
||||
return false;
|
||||
}
|
||||
return Utils::TestBit(bitmap_, 2 * position) &&
|
||||
Utils::TestBit(bitmap_, 2 * position + 1);
|
||||
return Utils::TestBit(bitmap_, kBitsPerParameter * position) &&
|
||||
Utils::TestBit(bitmap_, kBitsPerParameter * position + 1);
|
||||
}
|
||||
DART_FORCE_INLINE void SetUnboxedInteger(intptr_t position) {
|
||||
ASSERT(position < kCapacity);
|
||||
bitmap_ |= Utils::Bit<decltype(bitmap_)>(2 * position);
|
||||
ASSERT(!Utils::TestBit(bitmap_, 2 * position + 1));
|
||||
bitmap_ |= Utils::Bit<decltype(bitmap_)>(kBitsPerParameter * position);
|
||||
ASSERT(!Utils::TestBit(bitmap_, kBitsPerParameter * position + 1));
|
||||
}
|
||||
DART_FORCE_INLINE void SetUnboxedDouble(intptr_t position) {
|
||||
ASSERT(position < kCapacity);
|
||||
bitmap_ |= Utils::Bit<decltype(bitmap_)>(2 * position);
|
||||
bitmap_ |= Utils::Bit<decltype(bitmap_)>(2 * position + 1);
|
||||
bitmap_ |= Utils::Bit<decltype(bitmap_)>(kBitsPerParameter * position);
|
||||
bitmap_ |=
|
||||
Utils::Bit<decltype(bitmap_)>(kBitsPerParameter * position + 1);
|
||||
}
|
||||
DART_FORCE_INLINE uint64_t Value() const { return bitmap_; }
|
||||
DART_FORCE_INLINE bool IsEmpty() const { return bitmap_ == 0; }
|
||||
DART_FORCE_INLINE void Reset() { bitmap_ = 0; }
|
||||
DART_FORCE_INLINE bool HasUnboxedParameters() const {
|
||||
return (bitmap_ >> kBitsPerParameter) != 0;
|
||||
}
|
||||
DART_FORCE_INLINE bool HasUnboxedReturnValue() const {
|
||||
return (bitmap_ & kParameterBitmask) != 0;
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t bitmap_;
|
||||
|
||||
@@ -1657,6 +1657,7 @@ void SwitchableCallHandler::DoUnlinkedCall(const UnlinkedCall& unlinked,
|
||||
if (unlinked.can_patch_to_monomorphic()) {
|
||||
object = expected_cid.raw();
|
||||
code = target_code.raw();
|
||||
ASSERT(code.HasMonomorphicEntry());
|
||||
} else {
|
||||
object = MonomorphicSmiableCall::New(expected_cid.Value(), target_code);
|
||||
code = StubCode::MonomorphicSmiableCheck().raw();
|
||||
@@ -1909,6 +1910,7 @@ void SwitchableCallHandler::DoICDataMiss(const ICData& ic_data,
|
||||
Code::Handle(zone_, target_function.EnsureHasCode());
|
||||
const Smi& expected_cid =
|
||||
Smi::Handle(zone_, Smi::New(receiver_.GetClassId()));
|
||||
ASSERT(target_code.HasMonomorphicEntry());
|
||||
CodePatcher::PatchSwitchableCallAtWithMutatorsStopped(
|
||||
thread_, caller_frame_->pc(), caller_code_, expected_cid, target_code);
|
||||
arguments_.SetArgAt(0, target_code);
|
||||
@@ -2200,18 +2202,17 @@ DEFINE_RUNTIME_ENTRY(NoSuchMethodFromCallStub, 4) {
|
||||
// o.foo (o.get:foo) failed, closurize o.foo() if it exists.
|
||||
const auto& function_name =
|
||||
String::Handle(zone, Field::NameFromGetter(demangled_target_name));
|
||||
const auto& dyn_function_name = String::Handle(
|
||||
zone, is_dynamic_call ? Function::CreateDynamicInvocationForwarderName(
|
||||
function_name)
|
||||
: function_name.raw());
|
||||
while (!cls.IsNull()) {
|
||||
if (is_dynamic_call) {
|
||||
function = cls.LookupDynamicFunction(dyn_function_name);
|
||||
}
|
||||
// We don't generate dyn:* forwarders for method extractors so there is no
|
||||
// need to try to find a dyn:get:foo first (see assertion below)
|
||||
if (function.IsNull()) {
|
||||
function = cls.LookupDynamicFunction(function_name);
|
||||
}
|
||||
if (!function.IsNull()) {
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
ASSERT(!kernel::NeedsDynamicInvocationForwarder(Function::Handle(
|
||||
function.GetMethodExtractor(demangled_target_name))));
|
||||
#endif
|
||||
const Function& closure_function =
|
||||
Function::Handle(zone, function.ImplicitClosureFunction());
|
||||
const Object& result = Object::Handle(
|
||||
|
||||
Reference in New Issue
Block a user