Version 2.13.0-147.0.dev
Merge commit '26f0eba03b72eae65460413f5556599aa6370549' into 'dev'
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 5e82e3b..17573ee 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -513,16 +513,25 @@
}
/// Computes the appropriate set of context messages to report along with an
- /// error that may have occurred because [receiver] was not type promoted.
+ /// error that may have occurred because [expression] was not type promoted.
+ ///
+ /// If [expression] is `null`, it means the expression that was not type
+ /// promoted was an implicit `this`.
+ ///
+ /// [errorEntity] is the entity whose location will be associated with the
+ /// error. This is needed for test instrumentation.
+ ///
+ /// [whyNotPromoted] should be the non-promotion details returned by the flow
+ /// analysis engine.
List<DiagnosticMessage> computeWhyNotPromotedMessages(
- Expression? receiver,
+ Expression? expression,
SyntacticEntity errorEntity,
Map<DartType, NonPromotionReason>? whyNotPromoted) {
List<DiagnosticMessage> messages = [];
if (whyNotPromoted != null) {
for (var entry in whyNotPromoted.entries) {
var whyNotPromotedVisitor = _WhyNotPromotedVisitor(
- source, receiver, errorEntity, flowAnalysis!.dataForTesting);
+ source, expression, errorEntity, flowAnalysis!.dataForTesting);
if (typeSystem.isPotentiallyNullable(entry.key)) continue;
var message = entry.value.accept(whyNotPromotedVisitor);
if (message != null) {
@@ -3353,7 +3362,9 @@
PromotableElement, DartType> {
final Source source;
- final Expression? _receiver;
+ /// The expression that was not promoted, or `null` if the thing that was not
+ /// promoted was an implicit `this`.
+ final Expression? _expression;
final SyntacticEntity _errorEntity;
@@ -3364,7 +3375,7 @@
DartType? propertyType;
_WhyNotPromotedVisitor(
- this.source, this._receiver, this._errorEntity, this._dataForTesting);
+ this.source, this._expression, this._errorEntity, this._dataForTesting);
@override
DiagnosticMessage? visitDemoteViaExplicitWrite(
@@ -3410,16 +3421,17 @@
@override
DiagnosticMessage? visitPropertyNotPromoted(
PropertyNotPromoted<DartType> reason) {
- var receiver = _receiver;
+ var expression = _expression;
Element? receiverElement;
- if (receiver is SimpleIdentifier) {
- receiverElement = receiver.staticElement;
- } else if (receiver is PropertyAccess) {
- receiverElement = receiver.propertyName.staticElement;
- } else if (receiver is PrefixedIdentifier) {
- receiverElement = receiver.identifier.staticElement;
+ if (expression is SimpleIdentifier) {
+ receiverElement = expression.staticElement;
+ } else if (expression is PropertyAccess) {
+ receiverElement = expression.propertyName.staticElement;
+ } else if (expression is PrefixedIdentifier) {
+ receiverElement = expression.identifier.staticElement;
} else {
- assert(false, 'Unrecognized receiver: ${receiver.runtimeType}');
+ assert(false,
+ 'Unrecognized property access expression: ${expression.runtimeType}');
}
if (receiverElement is PropertyAccessorElement) {
propertyReference = receiverElement;
@@ -3427,7 +3439,7 @@
return _contextMessageForProperty(receiverElement, reason.propertyName);
} else {
assert(receiverElement == null,
- 'Unrecognized receiver element: ${receiverElement.runtimeType}');
+ 'Unrecognized property element: ${receiverElement.runtimeType}');
return null;
}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 93add07..21443af 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -5950,11 +5950,17 @@
// Peek to leave type parameters on top of stack.
List<TypeVariableBuilder> typeVariables = peek();
+ List<TypeBuilder> unboundTypes = [];
+ List<TypeVariableBuilder> unboundTypeVariables = [];
List<TypeBuilder> calculatedBounds = calculateBounds(
typeVariables,
libraryBuilder.loader.target.dynamicType,
libraryBuilder.loader.target.nullType,
- libraryBuilder.loader.target.objectClassBuilder);
+ libraryBuilder.loader.target.objectClassBuilder,
+ unboundTypes: unboundTypes,
+ unboundTypeVariables: unboundTypeVariables);
+ assert(unboundTypes.isEmpty,
+ "Found a type not bound to a declaration in BodyBuilder.");
for (int i = 0; i < typeVariables.length; ++i) {
typeVariables[i].defaultType = calculatedBounds[i];
typeVariables[i].defaultType.resolveIn(scope, typeVariables[i].charOffset,
@@ -5964,6 +5970,12 @@
libraryBuilder.loader.target.objectClassBuilder,
libraryBuilder.loader.target.dynamicType);
}
+ for (int i = 0; i < unboundTypeVariables.length; ++i) {
+ unboundTypeVariables[i].finish(
+ libraryBuilder,
+ libraryBuilder.loader.target.objectClassBuilder,
+ libraryBuilder.loader.target.dynamicType);
+ }
TypeVariableBuilder.finishNullabilities(
libraryBuilder, libraryBuilder.pendingNullabilities);
libraryBuilder.pendingNullabilities.clear();
diff --git a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
index 80f2dcb..57f8b57 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
@@ -378,7 +378,12 @@
/// (https://github.com/dart-lang/sdk/blob/master/docs/language/informal/instantiate-to-bound.md)
/// of the algorithm for details.
List<TypeBuilder> calculateBounds(List<TypeVariableBuilder> variables,
- TypeBuilder dynamicType, TypeBuilder bottomType, ClassBuilder objectClass) {
+ TypeBuilder dynamicType, TypeBuilder bottomType, ClassBuilder objectClass,
+ {List<TypeBuilder> unboundTypes,
+ List<TypeVariableBuilder> unboundTypeVariables}) {
+ assert(unboundTypes != null);
+ assert(unboundTypeVariables != null);
+
List<TypeBuilder> bounds =
new List<TypeBuilder>.filled(variables.length, null);
@@ -399,8 +404,12 @@
}
for (int variableIndex in component) {
TypeVariableBuilder variable = variables[variableIndex];
- bounds[variableIndex] = substituteRange(bounds[variableIndex],
- dynamicSubstitution, nullSubstitution, null, null,
+ bounds[variableIndex] = substituteRange(
+ bounds[variableIndex],
+ dynamicSubstitution,
+ nullSubstitution,
+ unboundTypes,
+ unboundTypeVariables,
variance: variable.variance);
}
}
@@ -414,8 +423,8 @@
nullSubstitution[variables[i]] = bottomType;
for (int j = 0; j < variables.length; j++) {
TypeVariableBuilder variable = variables[j];
- bounds[j] = substituteRange(
- bounds[j], substitution, nullSubstitution, null, null,
+ bounds[j] = substituteRange(bounds[j], substitution, nullSubstitution,
+ unboundTypes, unboundTypeVariables,
variance: variable.variance);
}
}
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index e409ff0..bb2c869 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -2937,11 +2937,20 @@
}
if (!haveErroneousBounds) {
+ List<TypeBuilder> unboundTypes = [];
+ List<TypeVariableBuilder> unboundTypeVariables = [];
List<TypeBuilder> calculatedBounds = calculateBounds(
variables,
dynamicType,
isNonNullableByDefault ? bottomType : nullType,
- objectClass);
+ objectClass,
+ unboundTypes: unboundTypes,
+ unboundTypeVariables: unboundTypeVariables);
+ for (TypeBuilder unboundType in unboundTypes) {
+ currentTypeParameterScopeBuilder
+ .addType(new UnresolvedType(unboundType, -1, null));
+ }
+ boundlessTypeVariables.addAll(unboundTypeVariables);
for (int i = 0; i < variables.length; ++i) {
variables[i].defaultType = calculatedBounds[i];
}
diff --git a/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart
new file mode 100644
index 0000000..70b0804
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2021, 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.
+
+foo<X extends Function<Y extends X>()>() {}
+
+main() {}
diff --git a/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.strong.expect b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.strong.expect
new file mode 100644
index 0000000..52d8793
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.strong.expect
@@ -0,0 +1,5 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+static method foo<X extends <Y extends self::foo::X = dynamic>() → dynamic = <Y extends dynamic = dynamic>() → dynamic>() → dynamic {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.strong.transformed.expect b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.strong.transformed.expect
new file mode 100644
index 0000000..52d8793
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.strong.transformed.expect
@@ -0,0 +1,5 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+static method foo<X extends <Y extends self::foo::X = dynamic>() → dynamic = <Y extends dynamic = dynamic>() → dynamic>() → dynamic {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.textual_outline.expect b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.textual_outline.expect
new file mode 100644
index 0000000..e6c43cd
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.textual_outline.expect
@@ -0,0 +1,2 @@
+foo<X extends Function<Y extends X>()>() {}
+main() {}
diff --git a/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..e6c43cd
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.textual_outline_modelled.expect
@@ -0,0 +1,2 @@
+foo<X extends Function<Y extends X>()>() {}
+main() {}
diff --git a/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.weak.expect b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.weak.expect
new file mode 100644
index 0000000..52d8793
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.weak.expect
@@ -0,0 +1,5 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+static method foo<X extends <Y extends self::foo::X = dynamic>() → dynamic = <Y extends dynamic = dynamic>() → dynamic>() → dynamic {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.weak.outline.expect b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.weak.outline.expect
new file mode 100644
index 0000000..3b0732a
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.weak.outline.expect
@@ -0,0 +1,7 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+static method foo<X extends <Y extends self::foo::X = dynamic>() → dynamic = <Y extends dynamic = dynamic>() → dynamic>() → dynamic
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.weak.transformed.expect b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.weak.transformed.expect
new file mode 100644
index 0000000..52d8793
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.weak.transformed.expect
@@ -0,0 +1,5 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+static method foo<X extends <Y extends self::foo::X = dynamic>() → dynamic = <Y extends dynamic = dynamic>() → dynamic>() → dynamic {}
+static method main() → dynamic {}
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index c845d8a..b33e519 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -2409,6 +2409,15 @@
call(FieldAddress(CODE_REG, target::Code::entry_point_offset(entry_kind)));
}
+void Assembler::CallVmStub(const Code& target) {
+ const Object& target_as_object = CastHandle<Object, Code>(target);
+ ASSERT(target::CanEmbedAsRawPointerInGeneratedCode(target_as_object));
+ call(Address::Absolute(
+ target::ToRawPointer(target_as_object) +
+ target::Code::entry_point_offset(CodeEntryKind::kNormal) -
+ kHeapObjectTag));
+}
+
void Assembler::CallToRuntime() {
call(Address(THR, target::Thread::call_to_runtime_entry_point_offset()));
}
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.h b/runtime/vm/compiler/assembler/assembler_ia32.h
index 82b9745..ed03442 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.h
+++ b/runtime/vm/compiler/assembler/assembler_ia32.h
@@ -770,6 +770,9 @@
bool movable_target = false,
CodeEntryKind entry_kind = CodeEntryKind::kNormal);
void CallToRuntime();
+ // Will not clobber any registers and can therefore be called with 5 live
+ // registers.
+ void CallVmStub(const Code& code);
void Call(Address target) { call(target); }
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index 09110ef..b5e050d 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -540,7 +540,11 @@
}
void FlowGraphCompiler::EmitCallToStub(const Code& stub) {
- __ Call(stub);
+ if (stub.InVMIsolateHeap()) {
+ __ CallVmStub(stub);
+ } else {
+ __ Call(stub);
+ }
AddStubCallTarget(stub);
}
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 8aa57f7..af6199b 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -5406,20 +5406,30 @@
}
void AssertSubtypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-#if defined(TARGET_ARCH_IA32)
- __ PushRegister(AssertSubtypeABI::kInstantiatorTypeArgumentsReg);
- __ PushRegister(AssertSubtypeABI::kFunctionTypeArgumentsReg);
- __ PushRegister(AssertSubtypeABI::kSubTypeReg);
- __ PushRegister(AssertSubtypeABI::kSuperTypeReg);
- __ PushRegister(AssertSubtypeABI::kDstNameReg);
- compiler->GenerateRuntimeCall(source(), deopt_id(), kSubtypeCheckRuntimeEntry,
- 5, locs());
-
- __ Drop(5);
-#else
compiler->GenerateStubCall(source(), StubCode::AssertSubtype(),
UntaggedPcDescriptors::kOther, locs());
-#endif
+}
+
+LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone,
+ bool opt) const {
+ const intptr_t kNumInputs = 2;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* locs = new (zone)
+ LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
+ locs->set_in(0, Location::RegisterLocation(
+ InstantiateTypeABI::kInstantiatorTypeArgumentsReg));
+ locs->set_in(1, Location::RegisterLocation(
+ InstantiateTypeABI::kFunctionTypeArgumentsReg));
+ locs->set_out(0,
+ Location::RegisterLocation(InstantiateTypeABI::kResultTypeReg));
+ return locs;
+}
+
+void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ LoadObject(InstantiateTypeABI::kTypeReg, type());
+ compiler->GenerateStubCall(source(), StubCode::InstantiateType(),
+ UntaggedPcDescriptors::kOther, locs(), deopt_id(),
+ env());
}
LocationSummary* DeoptimizeInstr::MakeLocationSummary(Zone* zone,
@@ -6515,6 +6525,8 @@
}
void EnterHandleScopeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ ASSERT(kEnterHandleScopeRuntimeEntry.is_leaf());
+
if (kind_ == Kind::kGetTopHandleScope) {
__ LoadMemoryValue(CallingConventions::kReturnReg, THR,
compiler::target::Thread::api_top_scope_offset());
@@ -6541,6 +6553,8 @@
}
void ExitHandleScopeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ ASSERT(kEnterHandleScopeRuntimeEntry.is_leaf());
+
Location arg_loc = FirstArgumentLocation();
__ EnterCFrame(arg_loc.IsRegister() ? 0 : compiler::target::kWordSize);
NoTemporaryAllocator no_temp;
@@ -6578,6 +6592,8 @@
}
void AllocateHandleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ ASSERT(kEnterHandleScopeRuntimeEntry.is_leaf());
+
Location arg_loc = FirstArgumentLocation();
__ EnterCFrame(arg_loc.IsRegister() ? 0 : compiler::target::kWordSize);
if (arg_loc.IsStackSlot()) {
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 3cf8ffc..5d39a46 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -364,7 +364,7 @@
// The instruction is guaranteed to not trigger GC on a non-exceptional
// path. If the conditions depend on parameters of the instruction, do not
// use this attribute but overload CanTriggerGC() instead.
- kNoGC = 1
+ kNoGC = 1,
};
};
@@ -392,7 +392,7 @@
M(NativeReturn, kNoGC) \
M(Throw, kNoGC) \
M(ReThrow, kNoGC) \
- M(Stop, _) \
+ M(Stop, kNoGC) \
M(Goto, kNoGC) \
M(IndirectGoto, kNoGC) \
M(Branch, kNoGC) \
@@ -402,10 +402,10 @@
M(SpecialParameter, kNoGC) \
M(ClosureCall, _) \
M(FfiCall, _) \
- M(EnterHandleScope, _) \
- M(ExitHandleScope, _) \
- M(AllocateHandle, _) \
- M(RawStoreField, _) \
+ M(EnterHandleScope, kNoGC) \
+ M(ExitHandleScope, kNoGC) \
+ M(AllocateHandle, kNoGC) \
+ M(RawStoreField, kNoGC) \
M(InstanceCall, _) \
M(PolymorphicInstanceCall, _) \
M(DispatchTableCall, _) \
@@ -470,19 +470,19 @@
M(Unbox, kNoGC) \
M(BoxInt64, _) \
M(UnboxInt64, kNoGC) \
- M(CaseInsensitiveCompare, _) \
+ M(CaseInsensitiveCompare, kNoGC) \
M(BinaryInt64Op, kNoGC) \
M(ShiftInt64Op, kNoGC) \
M(SpeculativeShiftInt64Op, kNoGC) \
M(UnaryInt64Op, kNoGC) \
M(CheckArrayBound, kNoGC) \
M(GenericCheckBound, kNoGC) \
- M(Constraint, _) \
+ M(Constraint, kNoGC) \
M(StringToCharCode, kNoGC) \
M(OneByteStringFromCharCode, kNoGC) \
M(StringInterpolate, _) \
M(Utf8Scan, kNoGC) \
- M(InvokeMathCFunction, _) \
+ M(InvokeMathCFunction, kNoGC) \
M(TruncDivMod, kNoGC) \
/*We could be more precise about when these 2 instructions can trigger GC.*/ \
M(GuardFieldClass, _) \
@@ -501,9 +501,9 @@
M(UnboxUint32, kNoGC) \
M(BoxInt32, _) \
M(UnboxInt32, kNoGC) \
- M(BoxUint8, _) \
+ M(BoxUint8, kNoGC) \
M(IntConverter, _) \
- M(BitCast, _) \
+ M(BitCast, kNoGC) \
M(Deoptimize, kNoGC) \
M(SimdOp, kNoGC)
@@ -5814,7 +5814,10 @@
// }
//
// under these assumptions:
-// - The start and end inputs are within the bounds of bytes and in smi range.
+// - The difference between start and end must be less than 2^30, since the
+// resulting length can be twice the input length (and the result has to be in
+// Smi range). This is guaranteed by `_Utf8Decoder.chunkSize` which is set to
+// `65536`.
// - The decoder._scanFlags field is unboxed or contains a smi.
// - The first 128 entries of the table have the value 1.
class Utf8ScanInstr : public TemplateDefinition<5, NoThrow> {
@@ -5848,6 +5851,7 @@
virtual bool HasUnknownSideEffects() const { return true; }
virtual bool ComputeCanDeoptimize() const { return false; }
virtual intptr_t DeoptimizationTarget() const { return DeoptId::kNone; }
+ virtual void InferRange(RangeAnalysis* analysis, Range* range);
virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
return kNotSpeculative;
@@ -6893,6 +6897,8 @@
virtual Definition* Canonicalize(FlowGraph* flow_graph);
+ virtual bool CanTriggerGC() const { return !ValueFitsSmi(); }
+
DEFINE_INSTRUCTION_TYPE_CHECK(BoxInteger)
private:
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index f14f74c..42c547a 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -3451,42 +3451,6 @@
__ Bind(&done);
}
-LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- const intptr_t kNumInputs = 2;
- const intptr_t kNumTemps = 0;
- LocationSummary* locs = new (zone)
- LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
- locs->set_in(0, Location::RegisterLocation(
- InstantiationABI::kInstantiatorTypeArgumentsReg));
- locs->set_in(1, Location::RegisterLocation(
- InstantiationABI::kFunctionTypeArgumentsReg));
- locs->set_out(0,
- Location::RegisterLocation(InstantiationABI::kResultTypeReg));
- return locs;
-}
-
-void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- const Register instantiator_type_args_reg = locs()->in(0).reg();
- const Register function_type_args_reg = locs()->in(1).reg();
- const Register result_reg = locs()->out(0).reg();
-
- // 'instantiator_type_args_reg' is a TypeArguments object (or null).
- // 'function_type_args_reg' is a TypeArguments object (or null).
- // A runtime call to instantiate the type is required.
- __ PushObject(Object::null_object()); // Make room for the result.
- __ PushObject(type());
- static_assert(InstantiationABI::kFunctionTypeArgumentsReg <
- InstantiationABI::kInstantiatorTypeArgumentsReg,
- "Should be ordered to push arguments with one instruction");
- __ PushList((1 << instantiator_type_args_reg) |
- (1 << function_type_args_reg));
- compiler->GenerateRuntimeCall(source(), deopt_id(),
- kInstantiateTypeRuntimeEntry, 3, locs());
- __ Drop(3); // Drop 2 type vectors, and uninstantiated type.
- __ Pop(result_reg); // Pop instantiated type.
-}
-
LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary(
Zone* zone,
bool opt) const {
@@ -6094,6 +6058,8 @@
}
void CaseInsensitiveCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ ASSERT(TargetFunction().is_leaf());
+
// Call the function.
__ CallRuntime(TargetFunction(), TargetFunction().argument_count());
}
@@ -6577,6 +6543,8 @@
}
void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ ASSERT(TargetFunction().is_leaf());
+
if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
InvokeDoublePow(compiler, this);
return;
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index ce2a0a9..48514db 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -3019,38 +3019,6 @@
__ Bind(&done);
}
-LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- const intptr_t kNumInputs = 2;
- const intptr_t kNumTemps = 0;
- LocationSummary* locs = new (zone)
- LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
- locs->set_in(0, Location::RegisterLocation(
- InstantiationABI::kInstantiatorTypeArgumentsReg));
- locs->set_in(1, Location::RegisterLocation(
- InstantiationABI::kFunctionTypeArgumentsReg));
- locs->set_out(0,
- Location::RegisterLocation(InstantiationABI::kResultTypeReg));
- return locs;
-}
-
-void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- const Register instantiator_type_args_reg = locs()->in(0).reg();
- const Register function_type_args_reg = locs()->in(1).reg();
- const Register result_reg = locs()->out(0).reg();
-
- // 'instantiator_type_args_reg' is a TypeArguments object (or null).
- // 'function_type_args_reg' is a TypeArguments object (or null).
- // A runtime call to instantiate the type is required.
- __ LoadObject(TMP, type());
- __ PushPair(TMP, NULL_REG);
- __ PushPair(function_type_args_reg, instantiator_type_args_reg);
- compiler->GenerateRuntimeCall(source(), deopt_id(),
- kInstantiateTypeRuntimeEntry, 3, locs());
- __ Drop(3); // Drop 2 type vectors, and uninstantiated type.
- __ Pop(result_reg); // Pop instantiated type.
-}
-
LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary(
Zone* zone,
bool opt) const {
@@ -5139,6 +5107,8 @@
}
void CaseInsensitiveCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ ASSERT(TargetFunction().is_leaf());
+
// Call the function.
__ CallRuntime(TargetFunction(), TargetFunction().argument_count());
}
@@ -5603,6 +5573,8 @@
}
void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ ASSERT(TargetFunction().is_leaf());
+
if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
InvokeDoublePow(compiler, this);
return;
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 900c929..c32a520 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -2772,39 +2772,6 @@
__ Bind(&done);
}
-LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- const intptr_t kNumInputs = 2;
- const intptr_t kNumTemps = 0;
- LocationSummary* locs = new (zone)
- LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
- locs->set_in(0, Location::RegisterLocation(
- InstantiationABI::kInstantiatorTypeArgumentsReg));
- locs->set_in(1, Location::RegisterLocation(
- InstantiationABI::kFunctionTypeArgumentsReg));
- locs->set_out(0,
- Location::RegisterLocation(InstantiationABI::kResultTypeReg));
- return locs;
-}
-
-void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- Register instantiator_type_args_reg = locs()->in(0).reg();
- Register function_type_args_reg = locs()->in(1).reg();
- Register result_reg = locs()->out(0).reg();
-
- // 'instantiator_type_args_reg' is a TypeArguments object (or null).
- // 'function_type_args_reg' is a TypeArguments object (or null).
- // A runtime call to instantiate the type is required.
- __ PushObject(Object::null_object()); // Make room for the result.
- __ PushObject(type());
- __ pushl(instantiator_type_args_reg); // Push instantiator type arguments.
- __ pushl(function_type_args_reg); // Push function type arguments.
- compiler->GenerateRuntimeCall(source(), deopt_id(),
- kInstantiateTypeRuntimeEntry, 3, locs());
- __ Drop(3); // Drop 2 type vectors, and uninstantiated type.
- __ popl(result_reg); // Pop instantiated type.
-}
-
LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary(
Zone* zone,
bool opt) const {
@@ -5034,6 +5001,8 @@
}
void CaseInsensitiveCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ ASSERT(TargetFunction().is_leaf());
+
// Save ESP. EDI is chosen because it is callee saved so we do not need to
// back it up before calling into the runtime.
static const Register kSavedSPReg = EDI;
@@ -5541,6 +5510,8 @@
}
void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ ASSERT(TargetFunction().is_leaf());
+
if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
InvokeDoublePow(compiler, this);
return;
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index 379ba84..085daca 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -3108,39 +3108,6 @@
__ Bind(&done);
}
-LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone,
- bool opt) const {
- const intptr_t kNumInputs = 2;
- const intptr_t kNumTemps = 0;
- LocationSummary* locs = new (zone)
- LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
- locs->set_in(0, Location::RegisterLocation(
- InstantiationABI::kInstantiatorTypeArgumentsReg));
- locs->set_in(1, Location::RegisterLocation(
- InstantiationABI::kFunctionTypeArgumentsReg));
- locs->set_out(0,
- Location::RegisterLocation(InstantiationABI::kResultTypeReg));
- return locs;
-}
-
-void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- Register instantiator_type_args_reg = locs()->in(0).reg();
- Register function_type_args_reg = locs()->in(1).reg();
- Register result_reg = locs()->out(0).reg();
-
- // 'instantiator_type_args_reg' is a TypeArguments object (or null).
- // 'function_type_args_reg' is a TypeArguments object (or null).
- // A runtime call to instantiate the type is required.
- __ PushObject(Object::null_object()); // Make room for the result.
- __ PushObject(type());
- __ pushq(instantiator_type_args_reg); // Push instantiator type arguments.
- __ pushq(function_type_args_reg); // Push function type arguments.
- compiler->GenerateRuntimeCall(source(), deopt_id(),
- kInstantiateTypeRuntimeEntry, 3, locs());
- __ Drop(3); // Drop 2 type vectors, and uninstantiated type.
- __ popq(result_reg); // Pop instantiated type.
-}
-
LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary(
Zone* zone,
bool opt) const {
@@ -5479,6 +5446,8 @@
}
void CaseInsensitiveCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ ASSERT(TargetFunction().is_leaf());
+
// Save RSP. R13 is chosen because it is callee saved so we do not need to
// back it up before calling into the runtime.
static const Register kSavedSPReg = R13;
@@ -5966,6 +5935,8 @@
}
void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ ASSERT(TargetFunction().is_leaf());
+
if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
InvokeDoublePow(compiler, this);
return;
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index e39dff8..51aa420 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -2914,6 +2914,12 @@
}
}
+void Utf8ScanInstr::InferRange(RangeAnalysis* analysis, Range* range) {
+ // The input bytes given to the Utf8Scan instruction are in non-negative Smi
+ // range and so is the resulting computed length.
+ *range = Range(RangeBoundary::FromConstant(0), RangeBoundary::MaxSmi());
+}
+
void IfThenElseInstr::InferRange(RangeAnalysis* analysis, Range* range) {
const intptr_t min = Utils::Minimum(if_true_, if_false_);
const intptr_t max = Utils::Maximum(if_true_, if_false_);
diff --git a/runtime/vm/compiler/stub_code_compiler.cc b/runtime/vm/compiler/stub_code_compiler.cc
index 3478028..76492e7 100644
--- a/runtime/vm/compiler/stub_code_compiler.cc
+++ b/runtime/vm/compiler/stub_code_compiler.cc
@@ -204,6 +204,19 @@
#endif
}
+void StubCodeCompiler::GenerateInstantiateTypeStub(Assembler* assembler) {
+ __ EnterStubFrame();
+ __ PushObject(Object::null_object());
+ __ PushRegister(InstantiateTypeABI::kTypeReg);
+ __ PushRegister(InstantiateTypeABI::kInstantiatorTypeArgumentsReg);
+ __ PushRegister(InstantiateTypeABI::kFunctionTypeArgumentsReg);
+ __ CallRuntime(kInstantiateTypeRuntimeEntry, /*argument_count=*/3);
+ __ Drop(3);
+ __ PopRegister(InstantiateTypeABI::kResultTypeReg);
+ __ LeaveStubFrame();
+ __ Ret();
+}
+
void StubCodeCompiler::GenerateInstanceOfStub(Assembler* assembler) {
__ EnterStubFrame();
__ PushObject(NullObject()); // Make room for the result.
diff --git a/runtime/vm/constants.h b/runtime/vm/constants.h
index 01d9d08..00e3f9b 100644
--- a/runtime/vm/constants.h
+++ b/runtime/vm/constants.h
@@ -19,6 +19,20 @@
namespace dart {
+// An architecture independent ABI for the InstantiateType stub.
+//
+// We re-use registers from another ABI to avoid duplicating this ABI across 4
+// architectures.
+struct InstantiateTypeABI {
+ static const Register kTypeReg =
+ InstantiationABI::kUninstantiatedTypeArgumentsReg;
+ static const Register kInstantiatorTypeArgumentsReg =
+ InstantiationABI::kInstantiatorTypeArgumentsReg;
+ static const Register kFunctionTypeArgumentsReg =
+ InstantiationABI::kFunctionTypeArgumentsReg;
+ static const Register kResultTypeReg = InstantiationABI::kResultTypeReg;
+};
+
class RegisterNames {
public:
static const char* RegisterName(Register reg) {
diff --git a/runtime/vm/stub_code_list.h b/runtime/vm/stub_code_list.h
index ea8d907..d1a200f 100644
--- a/runtime/vm/stub_code_list.h
+++ b/runtime/vm/stub_code_list.h
@@ -126,6 +126,7 @@
V(ReThrow) \
V(AssertBoolean) \
V(InstanceOf) \
+ V(InstantiateType) \
V(InstantiateTypeArguments) \
V(InstantiateTypeArgumentsMayShareInstantiatorTA) \
V(InstantiateTypeArgumentsMayShareFunctionTA) \
diff --git a/sdk/lib/_internal/vm/lib/convert_patch.dart b/sdk/lib/_internal/vm/lib/convert_patch.dart
index 851c554..22bf67c 100644
--- a/sdk/lib/_internal/vm/lib/convert_patch.dart
+++ b/sdk/lib/_internal/vm/lib/convert_patch.dart
@@ -1675,7 +1675,11 @@
"QQQQQQQQQQQQQQQQRRRRRbbbbbbbbbbb" // E0-FF
;
- /// Max chunk to scan at a time. Avoids staying away from safepoints too long.
+ /// Max chunk to scan at a time.
+ ///
+ /// Avoids staying away from safepoints too long.
+ /// The Utf8ScanInstr relies on this being small enough to ensure the
+ /// decoded length stays within Smi range.
static const int scanChunkSize = 65536;
/// Reset the decoder to a state where it is ready to decode a new string but
diff --git a/tools/VERSION b/tools/VERSION
index 41bc8a4..a5bbf8d 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 13
PATCH 0
-PRERELEASE 146
+PRERELEASE 147
PRERELEASE_PATCH 0
\ No newline at end of file