Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Unified Diff: pkg/compiler/lib/src/ssa/builder.dart

Issue 2260223002: Add SSA instructions for reified type information (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: reformat Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/compiler/lib/src/js_backend/backend_impact.dart ('k') | pkg/compiler/lib/src/ssa/codegen.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/ssa/builder.dart
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index 77025b0cc96e44c2c2224bc462b7a3d62b9d76ad..fe78ce20bc88ec77df550bc68dd242b7d74b257c 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -2327,10 +2327,12 @@ class SsaBuilder extends ast.Visitor
removeInlinedInstantiation(type);
// Create the runtime type information, if needed.
if (backend.classNeedsRti(classElement)) {
- // Read the values of the type arguments and create a list to set on the
- // newly create object. We can identify the case where the new list
- // would be of the form:
+ // Read the values of the type arguments and create a HTypeInfoExpression
+ // to set on the newly create object. We can identify the case where the
+ // expression would be of the form:
+ //
// [getTypeArgumentByIndex(this, 0), .., getTypeArgumentByIndex(this, k)]
+ //
// and k is the number of type arguments of this. If this is the case,
// we can simply copy the list from this.
@@ -2343,41 +2345,42 @@ class SsaBuilder extends ast.Visitor
// of `this`.
/// Helper to identify instructions that read a type variable without
- /// substitution (that is, directly use the index). These instructions
- /// are of the form:
- /// HInvokeStatic(getTypeArgumentByIndex, this, index)
+ /// substitution (that is, directly use the index). These are
+ /// HTypeInfoReadVariable instructions that require no substitution.
///
/// Return `true` if [instruction] is of that form and the index is the
/// next index in the sequence (held in [expectedIndex]).
+
+ /// TODO: Move this to a simplifier optimization of HTypeInfoExpression.
bool isIndexedTypeArgumentGet(HInstruction instruction) {
- if (instruction is! HInvokeStatic) return false;
- HInvokeStatic invoke = instruction;
- if (invoke.element != helpers.getTypeArgumentByIndex) {
- return false;
- }
- HConstant index = invoke.inputs[1];
- HInstruction newSource = invoke.inputs[0];
- if (newSource is! HThis) {
- return false;
- }
- if (source == null) {
- // This is the first match. Extract the context class for the type
- // variables and get the list of type variables to keep track of how
- // many arguments we need to process.
- source = newSource;
- contextClass = source.sourceElement.enclosingClass;
- remainingTypeVariables = contextClass.typeVariables.length;
- } else {
- assert(source == newSource);
+ if (instruction is HTypeInfoReadVariable) {
+ HInstruction newSource = instruction.inputs[0];
+ if (newSource is! HThis) {
+ return false;
+ }
+ if (source == null) {
+ // This is the first match. Extract the context class for the type
+ // variables and get the list of type variables to keep track of how
+ // many arguments we need to process.
+ source = newSource;
+ contextClass = source.sourceElement.enclosingClass;
+ if (needsSubstitutionForTypeVariableAccess(contextClass)) {
+ return false;
+ }
+ remainingTypeVariables = contextClass.typeVariables.length;
+ } else {
+ assert(source == newSource);
+ }
+ // If there are no more type variables, then there are more type
+ // arguments for the new object than the source has, and it can't be
+ // a copy. Otherwise remove one argument.
+ if (remainingTypeVariables == 0) return false;
+ remainingTypeVariables--;
+ // Check that the index is the one we expect.
+ int index = instruction.variable.element.index;
+ return index == expectedIndex++;
}
- // If there are no more type variables, then there are more type
- // arguments for the new object than the source has, and it can't be
- // a copy. Otherwise remove one argument.
- if (remainingTypeVariables == 0) return false;
- remainingTypeVariables--;
- // Check that the index is the one we expect.
- IntConstantValue constant = index.constant;
- return constant.primitiveValue == expectedIndex++;
+ return false;
}
List<HInstruction> typeArguments = <HInstruction>[];
@@ -2391,10 +2394,18 @@ class SsaBuilder extends ast.Visitor
});
if (source != null && allIndexed && remainingTypeVariables == 0) {
- copyRuntimeTypeInfo(source, newObject);
+ HInstruction typeInfo =
+ new HTypeInfoReadRaw(source, backend.dynamicType);
+ add(typeInfo);
+ newObject = callSetRuntimeTypeInfo(typeInfo, newObject);
} else {
- newObject =
- callSetRuntimeTypeInfo(classElement, typeArguments, newObject);
+ HInstruction typeInfo = new HTypeInfoExpression(
+ TypeInfoExpressionKind.INSTANCE,
+ classElement.thisType,
+ typeArguments,
+ backend.dynamicType);
+ add(typeInfo);
+ newObject = callSetRuntimeTypeInfo(typeInfo, newObject);
}
}
@@ -4710,32 +4721,15 @@ class SsaBuilder extends ast.Visitor
}
/**
- * Generate code to extract the type arguments from the object, substitute
- * them as an instance of the type we are testing against (if necessary), and
- * extract the type argument by the index of the variable in the list of type
- * variables for that class.
+ * Generate code to extract the type argument from the object.
*/
- HInstruction readTypeVariable(ClassElement cls, TypeVariableElement variable,
+ HInstruction readTypeVariable(TypeVariableType variable,
{SourceInformation sourceInformation}) {
assert(sourceElement.isInstanceMember);
-
+ assert(variable is! MethodTypeVariableType);
HInstruction target = localsHandler.readThis();
- HConstant index = graph.addConstantInt(variable.index, compiler);
-
- if (needsSubstitutionForTypeVariableAccess(cls)) {
- // TODO(ahe): Creating a string here is unfortunate. It is slow (due to
- // string concatenation in the implementation), and may prevent
- // segmentation of '$'.
- js.Name substitutionName = backend.namer.runtimeTypeName(cls);
- HInstruction substitutionNameInstr =
- graph.addConstantStringFromName(substitutionName, compiler);
- pushInvokeStatic(null, helpers.getRuntimeTypeArgument,
- [target, substitutionNameInstr, index],
- typeMask: backend.dynamicType, sourceInformation: sourceInformation);
- } else {
- pushInvokeStatic(null, helpers.getTypeArgumentByIndex, [target, index],
- typeMask: backend.dynamicType, sourceInformation: sourceInformation);
- }
+ push(new HTypeInfoReadVariable(variable, target, backend.dynamicType)
+ ..sourceInformation = sourceInformation);
return pop();
}
@@ -4753,6 +4747,9 @@ class SsaBuilder extends ast.Visitor
HInstruction addTypeVariableReference(TypeVariableType type,
{SourceInformation sourceInformation}) {
assert(assertTypeInContext(type));
+ if (type is MethodTypeVariableType) {
+ return graph.addConstantNull(compiler);
+ }
Element member = sourceElement;
bool isClosure = member.enclosingElement.isClosure;
if (isClosure) {
@@ -4777,8 +4774,7 @@ class SsaBuilder extends ast.Visitor
isInConstructorContext) {
// The type variable is stored on the "enclosing object" and needs to be
// accessed using the this-reference in the closure.
- return readTypeVariable(member.enclosingClass, type.element,
- sourceInformation: sourceInformation);
+ return readTypeVariable(type, sourceInformation: sourceInformation);
} else {
assert(member.isField);
// The type variable is stored in a parameter of the method.
@@ -4796,8 +4792,7 @@ class SsaBuilder extends ast.Visitor
sourceInformation: sourceInformation);
} else if (member.isInstanceMember) {
// The type variable is stored on the object.
- return readTypeVariable(member.enclosingClass, type.element,
- sourceInformation: sourceInformation);
+ return readTypeVariable(type, sourceInformation: sourceInformation);
} else {
reporter.internalError(
type.element, 'Unexpected type variable in static context.');
@@ -4819,15 +4814,14 @@ class SsaBuilder extends ast.Visitor
}
List<HInstruction> inputs = <HInstruction>[];
-
- js.Expression template =
- rtiEncoder.getTypeRepresentationWithPlaceholders(argument, (variable) {
- inputs.add(addTypeVariableReference(variable));
+ argument.forEachTypeVariable((variable) {
+ if (variable is! MethodTypeVariableType) {
+ inputs.add(analyzeTypeArgument(variable));
+ }
});
-
- js.Template code = new js.Template(null, template);
- HInstruction result = new HForeignCode(code, backend.stringType, inputs,
- nativeBehavior: native.NativeBehavior.PURE);
+ HInstruction result = new HTypeInfoExpression(
+ TypeInfoExpressionKind.COMPLETE, argument, inputs, backend.dynamicType)
+ ..sourceInformation = sourceInformation;
add(result);
return result;
}
@@ -4844,25 +4838,27 @@ class SsaBuilder extends ast.Visitor
});
// TODO(15489): Register at codegen.
registry?.registerInstantiation(type);
- return callSetRuntimeTypeInfo(type.element, inputs, newObject);
+ return callSetRuntimeTypeInfoWithTypeArguments(
+ type.element, inputs, newObject);
}
- void copyRuntimeTypeInfo(HInstruction source, HInstruction target) {
- Element copyHelper = helpers.copyTypeArguments;
- pushInvokeStatic(null, copyHelper, [source, target],
- sourceInformation: target.sourceInformation);
- pop();
- }
-
- HInstruction callSetRuntimeTypeInfo(ClassElement element,
+ HInstruction callSetRuntimeTypeInfoWithTypeArguments(ClassElement element,
List<HInstruction> rtiInputs, HInstruction newObject) {
- if (!backend.classNeedsRti(element) || element.typeVariables.isEmpty) {
+ if (!backend.classNeedsRti(element)) {
return newObject;
}
- HInstruction typeInfo = buildLiteralList(rtiInputs);
+ HInstruction typeInfo = new HTypeInfoExpression(
+ TypeInfoExpressionKind.INSTANCE,
+ element.thisType,
+ rtiInputs,
+ backend.dynamicType);
add(typeInfo);
+ return callSetRuntimeTypeInfo(typeInfo, newObject);
+ }
+ HInstruction callSetRuntimeTypeInfo(
+ HInstruction typeInfo, HInstruction newObject) {
// Set the runtime type information on the object.
Element typeInfoSetterElement = helpers.setRuntimeTypeInfo;
pushInvokeStatic(
@@ -4877,7 +4873,7 @@ class SsaBuilder extends ast.Visitor
stack.last is HInvokeStatic || stack.last == newObject,
message: "Unexpected `stack.last`: Found ${stack.last}, "
"expected ${newObject} or an HInvokeStatic. "
- "State: element=$element, rtiInputs=$rtiInputs, stack=$stack."));
+ "State: typeInfo=$typeInfo, stack=$stack."));
stack.last.instructionType = newObject.instructionType;
return pop();
}
@@ -5103,8 +5099,7 @@ class SsaBuilder extends ast.Visitor
List<HInstruction> inputs, ClassElement cls, InterfaceType expectedType,
{SourceInformation sourceInformation}) {
if (!backend.classNeedsRti(cls)) return;
- assert(expectedType.typeArguments.isEmpty ||
- cls.typeVariables.length == expectedType.typeArguments.length);
+ assert(cls.typeVariables.length == expectedType.typeArguments.length);
expectedType.typeArguments.forEach((DartType argument) {
inputs.add(
analyzeTypeArgument(argument, sourceInformation: sourceInformation));
@@ -6814,7 +6809,8 @@ class SsaBuilder extends ast.Visitor
}
// TODO(15489): Register at codegen.
registry?.registerInstantiation(type);
- return callSetRuntimeTypeInfo(type.element, arguments, object);
+ return callSetRuntimeTypeInfoWithTypeArguments(
+ type.element, arguments, object);
}
visitLiteralList(ast.LiteralList node) {
« no previous file with comments | « pkg/compiler/lib/src/js_backend/backend_impact.dart ('k') | pkg/compiler/lib/src/ssa/codegen.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698