Skip to content

Commit ded6933

Browse files
rakudramacommit-bot@chromium.org
authored andcommitted
New Rti SSA nodes
Change-Id: I1448239274803ca3e1dae4c602996662a11f2f1e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/105408 Commit-Queue: Stephen Adams <sra@google.com> Reviewed-by: Sigmund Cherem <sigmund@google.com>
1 parent 0960f72 commit ded6933

File tree

3 files changed

+278
-1
lines changed

3 files changed

+278
-1
lines changed

pkg/compiler/lib/src/ssa/codegen.dart

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3330,4 +3330,34 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
33303330
void visitRef(HRef node) {
33313331
visit(node.value);
33323332
}
3333+
3334+
@override
3335+
visitIsTest(HIsTest node) {
3336+
throw UnimplementedError('SsaCodeGenerator.visitIsTest');
3337+
}
3338+
3339+
@override
3340+
visitAsCheck(HAsCheck node) {
3341+
throw UnimplementedError('SsaCodeGenerator.visitAsCheck');
3342+
}
3343+
3344+
@override
3345+
visitSubtypeCheck(HSubtypeCheck node) {
3346+
throw UnimplementedError('SsaCodeGenerator.visitSubtypeCheck');
3347+
}
3348+
3349+
@override
3350+
visitLoadType(HLoadType node) {
3351+
throw UnimplementedError('SsaCodeGenerator.visitLoadType');
3352+
}
3353+
3354+
@override
3355+
visitTypeEval(HTypeEval node) {
3356+
throw UnimplementedError('SsaCodeGenerator.visitTypeEval');
3357+
}
3358+
3359+
@override
3360+
visitTypeBind(HTypeBind node) {
3361+
throw UnimplementedError('SsaCodeGenerator.visitTypeBind');
3362+
}
33333363
}

pkg/compiler/lib/src/ssa/nodes.dart

Lines changed: 211 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,14 @@ abstract class HVisitor<R> {
103103
R visitTypeInfoReadRaw(HTypeInfoReadRaw node);
104104
R visitTypeInfoReadVariable(HTypeInfoReadVariable node);
105105
R visitTypeInfoExpression(HTypeInfoExpression node);
106+
107+
// Instructions for 'dart:_rti'.
108+
R visitIsTest(HIsTest node);
109+
R visitAsCheck(HAsCheck node);
110+
R visitSubtypeCheck(HSubtypeCheck node);
111+
R visitLoadType(HLoadType node);
112+
R visitTypeEval(HTypeEval node);
113+
R visitTypeBind(HTypeBind node);
106114
}
107115

108116
abstract class HGraphVisitor {
@@ -584,8 +592,22 @@ class HBaseVisitor extends HGraphVisitor implements HVisitor {
584592
@override
585593
visitTypeInfoReadVariable(HTypeInfoReadVariable node) =>
586594
visitInstruction(node);
595+
587596
@override
588597
visitTypeInfoExpression(HTypeInfoExpression node) => visitInstruction(node);
598+
599+
@override
600+
visitIsTest(HIsTest node) => visitInstruction(node);
601+
@override
602+
visitAsCheck(HAsCheck node) => visitCheck(node);
603+
@override
604+
visitSubtypeCheck(HSubtypeCheck node) => visitCheck(node);
605+
@override
606+
visitLoadType(HLoadType node) => visitInstruction(node);
607+
@override
608+
visitTypeEval(HTypeEval node) => visitInstruction(node);
609+
@override
610+
visitTypeBind(HTypeBind node) => visitInstruction(node);
589611
}
590612

591613
class SubGraph {
@@ -1064,6 +1086,13 @@ abstract class HInstruction implements Spannable {
10641086
static const int BOOL_CONVERSION_TYPECODE = 45;
10651087
static const int PRIMITIVE_CHECK_TYPECODE = 46;
10661088

1089+
static const int IS_TEST_TYPECODE = 47;
1090+
static const int AS_CHECK_TYPECODE = 48;
1091+
static const int SUBTYPE_CHECK_TYPECODE = 49;
1092+
static const int LOAD_TYPE_TYPECODE = 50;
1093+
static const int TYPE_EVAL_TYPECODE = 51;
1094+
static const int TYPE_BIND_TYPECODE = 52;
1095+
10671096
HInstruction(this.inputs, this.instructionType)
10681097
: id = idCounter++,
10691098
usedBy = <HInstruction>[] {
@@ -1384,6 +1413,9 @@ abstract class HInstruction implements Spannable {
13841413
bool hasSameLoopHeaderAs(HInstruction other) {
13851414
return block.enclosingLoopHeader == other.block.enclosingLoopHeader;
13861415
}
1416+
1417+
@override
1418+
String toString() => '${this.runtimeType}()';
13871419
}
13881420

13891421
/// The set of uses of [source] that are dominated by [dominator].
@@ -3342,6 +3374,7 @@ class HIndexAssign extends HInstruction {
33423374
receiver.isNull(domain).isPotentiallyTrue;
33433375
}
33443376

3377+
/// Is-test using legacy constructor based typ representation.
33453378
class HIs extends HInstruction {
33463379
/// A check against a raw type: 'o is int', 'o is A'.
33473380
static const int RAW_CHECK = 0;
@@ -3476,7 +3509,7 @@ class HIsViaInterceptor extends HLateInstruction {
34763509
///
34773510
/// HLateValue is useful for naming values that would otherwise be generated at
34783511
/// use site, for example, if 'this' is used many times, replacing uses of
3479-
/// 'this' with HLateValhe(HThis) will have the effect of copying 'this' to a
3512+
/// 'this' with HLateValue(HThis) will have the effect of copying 'this' to a
34803513
/// temporary will reduce the size of minified code.
34813514
class HLateValue extends HLateInstruction {
34823515
HLateValue(HInstruction target) : super([target], target.instructionType);
@@ -3489,6 +3522,7 @@ class HLateValue extends HLateInstruction {
34893522
toString() => 'HLateValue($target)';
34903523
}
34913524

3525+
/// Type check or cast using legacy constructor-based type representation.
34923526
class HTypeConversion extends HCheck {
34933527
// Values for [kind].
34943528
static const int TYPE_CHECK = 0;
@@ -4299,3 +4333,179 @@ class HTypeInfoExpression extends HInstruction {
42994333
}
43004334
}
43014335
}
4336+
4337+
// -----------------------------------------------------------------------------
4338+
4339+
/// Is-test using Rti form of type expression.
4340+
///
4341+
/// This instruction can be used for any type. Tests for simple types are
4342+
/// lowered to other instructions, so this instruction remains for types that
4343+
/// depend on type variables and complex types.
4344+
class HIsTest extends HInstruction {
4345+
HIsTest(HInstruction checked, HInstruction rti, AbstractValue type)
4346+
: super([rti, checked], type) {
4347+
setUseGvn();
4348+
}
4349+
4350+
// The type input is first to facilitate the `type.is(value)` codegen pattern.
4351+
HInstruction get typeInput => inputs[0];
4352+
HInstruction get checkedInput => inputs[1];
4353+
4354+
@override
4355+
accept(HVisitor visitor) => visitor.visitIsTest(this);
4356+
4357+
@override
4358+
int typeCode() => HInstruction.IS_TEST_TYPECODE;
4359+
4360+
@override
4361+
bool typeEquals(HInstruction other) => other is HIsTest;
4362+
4363+
@override
4364+
bool dataEquals(HIsTest other) => true;
4365+
4366+
@override
4367+
String toString() => 'HIsTest()';
4368+
}
4369+
4370+
/// Type cast or type check using Rti form of type expression.
4371+
class HAsCheck extends HCheck {
4372+
final bool isTypeError;
4373+
4374+
HAsCheck(HInstruction checked, HInstruction rti, this.isTypeError,
4375+
AbstractValue type)
4376+
: super([rti, checked], type) {}
4377+
4378+
// The type input is first to facilitate the `type.as(value)` codegen pattern.
4379+
HInstruction get typeInput => inputs[0];
4380+
@override
4381+
HInstruction get checkedInput => inputs[1];
4382+
4383+
@override
4384+
accept(HVisitor visitor) => visitor.visitAsCheck(this);
4385+
4386+
@override
4387+
int typeCode() => HInstruction.AS_CHECK_TYPECODE;
4388+
4389+
@override
4390+
bool typeEquals(HInstruction other) => other is HAsCheck;
4391+
4392+
@override
4393+
bool dataEquals(HAsCheck other) {
4394+
return isTypeError == other.isTypeError;
4395+
}
4396+
4397+
@override
4398+
String toString() {
4399+
String error = isTypeError ? 'TypeError' : 'CastError';
4400+
return 'HAsCheck($error)';
4401+
}
4402+
}
4403+
4404+
/// Subtype check comparing two Rti types.
4405+
class HSubtypeCheck extends HCheck {
4406+
HSubtypeCheck(
4407+
HInstruction subtype, HInstruction supertype, AbstractValue type)
4408+
: super([subtype, supertype], type) {
4409+
setUseGvn();
4410+
}
4411+
4412+
HInstruction get typeInput => inputs[1];
4413+
4414+
@override
4415+
accept(HVisitor visitor) => visitor.visitSubtypeCheck(this);
4416+
4417+
@override
4418+
int typeCode() => HInstruction.SUBTYPE_CHECK_TYPECODE;
4419+
4420+
@override
4421+
bool typeEquals(HInstruction other) => other is HSubtypeCheck;
4422+
4423+
@override
4424+
bool dataEquals(HSubtypeCheck other) => true;
4425+
4426+
@override
4427+
String toString() => 'HSubtypeCheck()';
4428+
}
4429+
4430+
/// Common superclass for instructions that generate Rti values.
4431+
abstract class HRtiInstruction extends HInstruction {
4432+
HRtiInstruction(List<HInstruction> inputs, AbstractValue type)
4433+
: super(inputs, type);
4434+
}
4435+
4436+
/// Evaluates an Rti type recipe in the global environment.
4437+
class HLoadType extends HRtiInstruction {
4438+
DartType typeExpression; // TODO(sra): Allow a type environment expression.
4439+
4440+
HLoadType(this.typeExpression, AbstractValue type) : super([], type) {
4441+
setUseGvn();
4442+
}
4443+
4444+
@override
4445+
accept(HVisitor visitor) => visitor.visitLoadType(this);
4446+
4447+
@override
4448+
int typeCode() => HInstruction.LOAD_TYPE_TYPECODE;
4449+
4450+
@override
4451+
bool typeEquals(HInstruction other) => other is HLoadType;
4452+
4453+
@override
4454+
bool dataEquals(HLoadType other) {
4455+
return typeExpression == other.typeExpression;
4456+
}
4457+
4458+
@override
4459+
String toString() => 'HLoadType($typeExpression)';
4460+
}
4461+
4462+
/// Evaluates an Rti type recipe in an Rti environment.
4463+
class HTypeEval extends HRtiInstruction {
4464+
DartType typeExpression; // TODO(sra); Allow a type environment expression.
4465+
4466+
HTypeEval(HInstruction environment, this.typeExpression, AbstractValue type)
4467+
: super([environment], type) {
4468+
setUseGvn();
4469+
}
4470+
4471+
@override
4472+
accept(HVisitor visitor) => visitor.visitTypeEval(this);
4473+
4474+
@override
4475+
int typeCode() => HInstruction.TYPE_EVAL_TYPECODE;
4476+
4477+
@override
4478+
bool typeEquals(HInstruction other) => other is HTypeEval;
4479+
4480+
@override
4481+
bool dataEquals(HTypeEval other) {
4482+
return typeExpression == other.typeExpression;
4483+
}
4484+
4485+
@override
4486+
String toString() => 'HTypeEval($typeExpression)';
4487+
}
4488+
4489+
/// Extends an Rti type environment with generic function types.
4490+
class HTypeBind extends HRtiInstruction {
4491+
HTypeBind(
4492+
HInstruction environment, HInstruction typeArguments, AbstractValue type)
4493+
: super([environment, typeArguments], type) {
4494+
setUseGvn();
4495+
}
4496+
4497+
@override
4498+
accept(HVisitor visitor) => visitor.visitTypeBind(this);
4499+
4500+
@override
4501+
int typeCode() => HInstruction.TYPE_BIND_TYPECODE;
4502+
4503+
@override
4504+
bool typeEquals(HInstruction other) => other is HTypeBind;
4505+
4506+
@override
4507+
bool dataEquals(HTypeBind other) => true;
4508+
4509+
@override
4510+
String toString() => 'HTypeBind()';
4511+
}

pkg/compiler/lib/src/ssa/ssa_tracer.dart

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,4 +673,41 @@ class HInstructionStringifier implements HVisitor<String> {
673673
String visitYield(HYield node) {
674674
return "Yield${node.hasStar ? "*" : ""}: ${temporaryId(node.inputs[0])}";
675675
}
676+
677+
@override
678+
visitIsTest(HIsTest node) {
679+
var inputs = node.inputs.map(temporaryId).join(', ');
680+
return "IsTest: $inputs";
681+
}
682+
683+
@override
684+
visitAsCheck(HAsCheck node) {
685+
var inputs = node.inputs.map(temporaryId).join(', ');
686+
String error = node.isTypeError ? 'TypeError' : 'CastError';
687+
return "AsCheck: $error $inputs";
688+
}
689+
690+
@override
691+
visitSubtypeCheck(HSubtypeCheck node) {
692+
var inputs = node.inputs.map(temporaryId).join(', ');
693+
return "SubtypeCheck: $inputs";
694+
}
695+
696+
@override
697+
visitLoadType(HLoadType node) {
698+
var inputs = node.inputs.map(temporaryId).join(', ');
699+
return "LoadType: $inputs";
700+
}
701+
702+
@override
703+
visitTypeEval(HTypeEval node) {
704+
var inputs = node.inputs.map(temporaryId).join(', ');
705+
return "TypeEval: $inputs";
706+
}
707+
708+
@override
709+
visitTypeBind(HTypeBind node) {
710+
var inputs = node.inputs.map(temporaryId).join(', ');
711+
return "TypeBind: $inputs";
712+
}
676713
}

0 commit comments

Comments
 (0)