Skip to content

Commit 7aae1f6

Browse files
sstricklcommit-bot@chromium.org
authored andcommitted
[vm] Relax AssertSubtype to allow non-constant sub and super types.
Previously, AssertSubtype instructions could only be created with a compile-time AbstractType value for sub_type and super_type. Relax this so that AssertSubtype instructions can be created with possibly non-constant Values instead. Currently, all AssertSubtype uses still have constant sub- and supertypes, so for now we check at code generation that we indeed have constants for these values and only handle the constant case. Thus, there should be no impact on size or speed of the generated code from these changes. Follow-up work will add code generation for non-constant sub- and supertypes and add uses the generalized form. Bug: #40813 Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-linux-release-simarm64-try Change-Id: Ib1512b3e07a016d68a8e0c670ce857b8ac1b2777 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/147520 Commit-Queue: Tess Strickland <[email protected]> Reviewed-by: Martin Kustermann <[email protected]>
1 parent 874588a commit 7aae1f6

File tree

10 files changed

+74
-111
lines changed

10 files changed

+74
-111
lines changed

runtime/vm/compiler/backend/il.cc

Lines changed: 50 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -975,46 +975,38 @@ bool GuardFieldTypeInstr::AttributesEqual(Instruction* other) const {
975975
}
976976

977977
Instruction* AssertSubtypeInstr::Canonicalize(FlowGraph* flow_graph) {
978-
// If all values for type parameters are known (i.e. from instantiator and
979-
// function) we can instantiate the sub and super type and remove this
980-
// instruction if the subtype test succeeds.
981-
ConstantInstr* constant_instantiator_type_args =
982-
instantiator_type_arguments()->definition()->AsConstant();
983-
ConstantInstr* constant_function_type_args =
984-
function_type_arguments()->definition()->AsConstant();
985-
if ((constant_instantiator_type_args != NULL) &&
986-
(constant_function_type_args != NULL)) {
987-
ASSERT(constant_instantiator_type_args->value().IsNull() ||
988-
constant_instantiator_type_args->value().IsTypeArguments());
989-
ASSERT(constant_function_type_args->value().IsNull() ||
990-
constant_function_type_args->value().IsTypeArguments());
991-
992-
Zone* Z = Thread::Current()->zone();
993-
const TypeArguments& instantiator_type_args = TypeArguments::Handle(
994-
Z,
995-
TypeArguments::RawCast(constant_instantiator_type_args->value().raw()));
996-
997-
const TypeArguments& function_type_args = TypeArguments::Handle(
998-
Z, TypeArguments::RawCast(constant_function_type_args->value().raw()));
999-
1000-
AbstractType& sub_type = AbstractType::Handle(Z, sub_type_.raw());
1001-
AbstractType& super_type = AbstractType::Handle(Z, super_type_.raw());
1002-
if (AbstractType::InstantiateAndTestSubtype(&sub_type, &super_type,
1003-
instantiator_type_args,
1004-
function_type_args)) {
1005-
return NULL;
978+
// If all inputs are constant, we can instantiate the sub and super type and
979+
// remove this instruction if the subtype test succeeds.
980+
if (super_type()->BindsToConstant() && sub_type()->BindsToConstant() &&
981+
instantiator_type_arguments()->BindsToConstant() &&
982+
function_type_arguments()->BindsToConstant()) {
983+
auto Z = Thread::Current()->zone();
984+
const auto& constant_instantiator_type_args =
985+
instantiator_type_arguments()->BoundConstant().IsNull()
986+
? TypeArguments::null_type_arguments()
987+
: TypeArguments::Cast(
988+
instantiator_type_arguments()->BoundConstant());
989+
const auto& constant_function_type_args =
990+
function_type_arguments()->BoundConstant().IsNull()
991+
? TypeArguments::null_type_arguments()
992+
: TypeArguments::Cast(function_type_arguments()->BoundConstant());
993+
auto& constant_sub_type = AbstractType::Handle(
994+
Z, AbstractType::Cast(sub_type()->BoundConstant()).raw());
995+
auto& constant_super_type = AbstractType::Handle(
996+
Z, AbstractType::Cast(super_type()->BoundConstant()).raw());
997+
998+
ASSERT(!constant_super_type.IsTypeRef());
999+
ASSERT(!constant_sub_type.IsTypeRef());
1000+
1001+
if (AbstractType::InstantiateAndTestSubtype(
1002+
&constant_sub_type, &constant_super_type,
1003+
constant_instantiator_type_args, constant_function_type_args)) {
1004+
return nullptr;
10061005
}
10071006
}
10081007
return this;
10091008
}
10101009

1011-
bool AssertSubtypeInstr::AttributesEqual(Instruction* other) const {
1012-
AssertSubtypeInstr* other_assert = other->AsAssertSubtype();
1013-
ASSERT(other_assert != NULL);
1014-
return super_type().raw() == other_assert->super_type().raw() &&
1015-
sub_type().raw() == other_assert->sub_type().raw();
1016-
}
1017-
10181010
bool StrictCompareInstr::AttributesEqual(Instruction* other) const {
10191011
StrictCompareInstr* other_op = other->AsStrictCompare();
10201012
ASSERT(other_op != NULL);
@@ -5052,14 +5044,32 @@ void AssertAssignableInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
50525044
ASSERT(locs()->in(0).reg() == locs()->out(0).reg());
50535045
}
50545046

5055-
void AssertSubtypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5056-
ASSERT(sub_type().IsFinalized());
5057-
ASSERT(super_type().IsFinalized());
5047+
LocationSummary* AssertSubtypeInstr::MakeLocationSummary(Zone* zone,
5048+
bool opt) const {
5049+
if (!sub_type()->BindsToConstant() || !super_type()->BindsToConstant()) {
5050+
// TODO(dartbug.com/40813): Handle setting up the non-constant case.
5051+
UNREACHABLE();
5052+
}
5053+
const intptr_t kNumInputs = 4;
5054+
const intptr_t kNumTemps = 0;
5055+
LocationSummary* summary = new (zone)
5056+
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
5057+
summary->set_in(0, Location::RegisterLocation(
5058+
TypeTestABI::kInstantiatorTypeArgumentsReg));
5059+
summary->set_in(
5060+
1, Location::RegisterLocation(TypeTestABI::kFunctionTypeArgumentsReg));
5061+
summary->set_in(2,
5062+
Location::Constant(sub_type()->definition()->AsConstant()));
5063+
summary->set_in(3,
5064+
Location::Constant(super_type()->definition()->AsConstant()));
5065+
return summary;
5066+
}
50585067

5068+
void AssertSubtypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
50595069
__ PushRegister(locs()->in(0).reg());
50605070
__ PushRegister(locs()->in(1).reg());
5061-
__ PushObject(sub_type());
5062-
__ PushObject(super_type());
5071+
__ PushObject(locs()->in(2).constant());
5072+
__ PushObject(locs()->in(3).constant());
50635073
__ PushObject(dst_name());
50645074

50655075
compiler->GenerateRuntimeCall(token_pos(), deopt_id(),

runtime/vm/compiler/backend/il.h

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3456,37 +3456,33 @@ class UnboxedConstantInstr : public ConstantInstr {
34563456
// Checks that one type is a subtype of another (e.g. for type parameter bounds
34573457
// checking). Throws a TypeError otherwise. Both types are instantiated at
34583458
// runtime as necessary.
3459-
class AssertSubtypeInstr : public TemplateInstruction<2, Throws, Pure> {
3459+
class AssertSubtypeInstr : public TemplateInstruction<4, Throws, Pure> {
34603460
public:
34613461
AssertSubtypeInstr(TokenPosition token_pos,
34623462
Value* instantiator_type_arguments,
34633463
Value* function_type_arguments,
3464-
const AbstractType& sub_type,
3465-
const AbstractType& super_type,
3464+
Value* sub_type,
3465+
Value* super_type,
34663466
const String& dst_name,
34673467
intptr_t deopt_id)
34683468
: TemplateInstruction(deopt_id),
34693469
token_pos_(token_pos),
3470-
sub_type_(AbstractType::ZoneHandle(sub_type.raw())),
3471-
super_type_(AbstractType::ZoneHandle(super_type.raw())),
34723470
dst_name_(String::ZoneHandle(dst_name.raw())) {
3473-
ASSERT(!super_type.IsNull());
3474-
ASSERT(!super_type.IsTypeRef());
3475-
ASSERT(!sub_type.IsNull());
3476-
ASSERT(!sub_type.IsTypeRef());
34773471
ASSERT(!dst_name.IsNull());
34783472
SetInputAt(0, instantiator_type_arguments);
34793473
SetInputAt(1, function_type_arguments);
3474+
SetInputAt(2, sub_type);
3475+
SetInputAt(3, super_type);
34803476
}
34813477

34823478
DECLARE_INSTRUCTION(AssertSubtype);
34833479

34843480
Value* instantiator_type_arguments() const { return inputs_[0]; }
34853481
Value* function_type_arguments() const { return inputs_[1]; }
3482+
Value* sub_type() const { return inputs_[2]; }
3483+
Value* super_type() const { return inputs_[3]; }
34863484

34873485
virtual TokenPosition token_pos() const { return token_pos_; }
3488-
const AbstractType& super_type() const { return super_type_; }
3489-
const AbstractType& sub_type() const { return sub_type_; }
34903486
const String& dst_name() const { return dst_name_; }
34913487

34923488
virtual bool ComputeCanDeoptimize() const {
@@ -3497,14 +3493,12 @@ class AssertSubtypeInstr : public TemplateInstruction<2, Throws, Pure> {
34973493

34983494
virtual Instruction* Canonicalize(FlowGraph* flow_graph);
34993495

3500-
virtual bool AttributesEqual(Instruction* other) const;
3496+
virtual bool AttributesEqual(Instruction* other) const { return true; }
35013497

35023498
PRINT_OPERANDS_TO_SUPPORT
35033499

35043500
private:
35053501
const TokenPosition token_pos_;
3506-
AbstractType& sub_type_;
3507-
AbstractType& super_type_;
35083502
const String& dst_name_;
35093503

35103504
DISALLOW_COPY_AND_ASSIGN(AssertSubtypeInstr);

runtime/vm/compiler/backend/il_arm.cc

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -698,17 +698,6 @@ LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone,
698698
return summary;
699699
}
700700

701-
LocationSummary* AssertSubtypeInstr::MakeLocationSummary(Zone* zone,
702-
bool opt) const {
703-
const intptr_t kNumInputs = 2;
704-
const intptr_t kNumTemps = 0;
705-
LocationSummary* summary = new (zone)
706-
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
707-
summary->set_in(0, Location::RegisterLocation(R2)); // Instant. type args.
708-
summary->set_in(1, Location::RegisterLocation(R1)); // Function type args.
709-
return summary;
710-
}
711-
712701
static Condition TokenKindToSmiCondition(Token::Kind kind) {
713702
switch (kind) {
714703
case Token::kEQ:

runtime/vm/compiler/backend/il_arm64.cc

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -589,17 +589,6 @@ LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone,
589589
return summary;
590590
}
591591

592-
LocationSummary* AssertSubtypeInstr::MakeLocationSummary(Zone* zone,
593-
bool opt) const {
594-
const intptr_t kNumInputs = 2;
595-
const intptr_t kNumTemps = 0;
596-
LocationSummary* summary = new (zone)
597-
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
598-
summary->set_in(0, Location::RegisterLocation(R2)); // Instant. type args.
599-
summary->set_in(1, Location::RegisterLocation(R1)); // Function type args.
600-
return summary;
601-
}
602-
603592
static Condition TokenKindToSmiCondition(Token::Kind kind) {
604593
switch (kind) {
605594
case Token::kEQ:

runtime/vm/compiler/backend/il_ia32.cc

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -378,17 +378,6 @@ LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone,
378378
return summary;
379379
}
380380

381-
LocationSummary* AssertSubtypeInstr::MakeLocationSummary(Zone* zone,
382-
bool opt) const {
383-
const intptr_t kNumInputs = 2;
384-
const intptr_t kNumTemps = 0;
385-
LocationSummary* summary = new (zone)
386-
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
387-
summary->set_in(0, Location::RegisterLocation(EDX)); // Instant. type args.
388-
summary->set_in(1, Location::RegisterLocation(ECX)); // Function type args.
389-
return summary;
390-
}
391-
392381
static Condition TokenKindToSmiCondition(Token::Kind kind) {
393382
switch (kind) {
394383
case Token::kEQ:

runtime/vm/compiler/backend/il_printer.cc

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -415,10 +415,6 @@ void DropTempsInstr::PrintOperandsTo(BufferFormatter* f) const {
415415
}
416416
}
417417

418-
static const char* TypeToUserVisibleName(const AbstractType& type) {
419-
return String::Handle(type.UserVisibleName()).ToCString();
420-
}
421-
422418
void AssertAssignableInstr::PrintOperandsTo(BufferFormatter* f) const {
423419
value()->PrintTo(f);
424420
f->Print(", ");
@@ -432,8 +428,10 @@ void AssertAssignableInstr::PrintOperandsTo(BufferFormatter* f) const {
432428
}
433429

434430
void AssertSubtypeInstr::PrintOperandsTo(BufferFormatter* f) const {
435-
f->Print("%s, %s, '%s',", TypeToUserVisibleName(sub_type()),
436-
TypeToUserVisibleName(super_type()), dst_name().ToCString());
431+
sub_type()->PrintTo(f);
432+
f->Print(", ");
433+
super_type()->PrintTo(f);
434+
f->Print(", '%s', ", dst_name().ToCString());
437435
f->Print(" instantiator_type_args(");
438436
instantiator_type_arguments()->PrintTo(f);
439437
f->Print("), function_type_args(");

runtime/vm/compiler/backend/il_x64.cc

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -545,17 +545,6 @@ LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone,
545545
return summary;
546546
}
547547

548-
LocationSummary* AssertSubtypeInstr::MakeLocationSummary(Zone* zone,
549-
bool opt) const {
550-
const intptr_t kNumInputs = 2;
551-
const intptr_t kNumTemps = 0;
552-
LocationSummary* summary = new (zone)
553-
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
554-
summary->set_in(0, Location::RegisterLocation(RDX)); // Instant. type args.
555-
summary->set_in(1, Location::RegisterLocation(RCX)); // Function type args.
556-
return summary;
557-
}
558-
559548
static Condition TokenKindToIntCondition(Token::Kind kind) {
560549
switch (kind) {
561550
case Token::kEQ:

runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,8 +1402,8 @@ void BytecodeFlowGraphBuilder::BuildAssertSubtype() {
14021402
LoadStackSlots(5);
14031403

14041404
const String& dst_name = String::Cast(PopConstant().value());
1405-
const AbstractType& super_type = AbstractType::Cast(PopConstant().value());
1406-
const AbstractType& sub_type = AbstractType::Cast(PopConstant().value());
1405+
Value* super_type = Pop();
1406+
Value* sub_type = Pop();
14071407
Value* function_type_args = Pop();
14081408
Value* instantiator_type_args = Pop();
14091409

runtime/vm/compiler/frontend/kernel_to_il.cc

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1587,15 +1587,20 @@ Fragment FlowGraphBuilder::AssertAssignableLoadTypeArguments(
15871587
}
15881588

15891589
Fragment FlowGraphBuilder::AssertSubtype(TokenPosition position,
1590-
const AbstractType& sub_type,
1591-
const AbstractType& super_type,
1590+
const AbstractType& sub_type_value,
1591+
const AbstractType& super_type_value,
15921592
const String& dst_name) {
15931593
Fragment instructions;
15941594

15951595
instructions += LoadInstantiatorTypeArguments();
1596-
Value* instantiator_type_args = Pop();
15971596
instructions += LoadFunctionTypeArguments();
1597+
instructions += Constant(AbstractType::ZoneHandle(sub_type_value.raw()));
1598+
instructions += Constant(AbstractType::ZoneHandle(super_type_value.raw()));
1599+
1600+
Value* super_type = Pop();
1601+
Value* sub_type = Pop();
15981602
Value* function_type_args = Pop();
1603+
Value* instantiator_type_args = Pop();
15991604

16001605
AssertSubtypeInstr* instr = new (Z)
16011606
AssertSubtypeInstr(position, instantiator_type_args, function_type_args,

runtime/vm/runtime_entry.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -446,8 +446,8 @@ DEFINE_RUNTIME_ENTRY(SubtypeCheck, 5) {
446446
AbstractType::CheckedHandle(zone, arguments.ArgAt(3));
447447
const String& dst_name = String::CheckedHandle(zone, arguments.ArgAt(4));
448448

449-
ASSERT(!subtype.IsNull());
450-
ASSERT(!supertype.IsNull());
449+
ASSERT(!subtype.IsNull() && !subtype.IsTypeRef());
450+
ASSERT(!supertype.IsNull() && !supertype.IsTypeRef());
451451

452452
// The supertype or subtype may not be instantiated.
453453
if (AbstractType::InstantiateAndTestSubtype(

0 commit comments

Comments
 (0)