dart2js-kernel: Implement Let and PropertySet.

The Accessor builders capture some subexpressions to help map kernel
Nodes to Ast Nodes.

R=asgerf@google.com

Review URL: https://codereview.chromium.org/2526123002 .
This commit is contained in:
Stephen Adams 2016-11-26 12:42:37 -08:00
parent d92107e01d
commit b20b10a0af
5 changed files with 95 additions and 16 deletions

View file

@ -73,6 +73,7 @@ class Kernel {
final Map<ir.Node, Element> nodeToElement = <ir.Node, Element>{};
final Map<ir.Node, Node> nodeToAst = <ir.Node, Node>{};
final Map<ir.Node, Node> nodeToAstOperator = <ir.Node, Node>{};
/// FIFO queue of work that needs to be completed before the returned AST
/// nodes are correct.

View file

@ -1230,6 +1230,7 @@ class KernelVisitor extends Object
@override
ir.Expression visitCompoundIndexSet(SendSet node, Node receiver, Node index,
AssignmentOperator operator, Node rhs, _) {
// TODO(sra): Find binary operator.
return buildIndexAccessor(receiver, index).buildCompoundAssignment(
kernel.irName(operator.selectorName, currentElement),
visitForValue(rhs),
@ -1289,7 +1290,8 @@ class KernelVisitor extends Object
receiver == null ? new ir.ThisExpression() : visitForValue(receiver);
ir.Expression compound = buildCompound(
PropertyAccessor.make(receiverNode, nameToIrName(name), null, null),
rhs);
rhs,
node);
if (compound is ir.VariableSet) {
associateNode(compound.value, node);
} else {
@ -1720,19 +1722,32 @@ class KernelVisitor extends Object
return buildLocalGet(element);
}
ir.Expression buildCompound(Accessor accessor, CompoundRhs rhs) {
ir.Expression buildCompound(
Accessor accessor, CompoundRhs rhs, SendSet node) {
ir.Name name = kernel.irName(rhs.operator.selectorName, currentElement);
ir.Expression result;
switch (rhs.kind) {
case CompoundKind.POSTFIX:
return accessor.buildPostfixIncrement(name, voidContext: isVoidContext);
result =
accessor.buildPostfixIncrement(name, voidContext: isVoidContext);
break;
case CompoundKind.PREFIX:
return accessor.buildPrefixIncrement(name, voidContext: isVoidContext);
result =
accessor.buildPrefixIncrement(name, voidContext: isVoidContext);
break;
case CompoundKind.ASSIGNMENT:
return accessor.buildCompoundAssignment(name, visitForValue(rhs.rhs),
result = accessor.buildCompoundAssignment(name, visitForValue(rhs.rhs),
voidContext: isVoidContext);
break;
}
assert(accessor.builtBinary != null);
kernel.nodeToAstOperator[accessor.builtBinary] = node;
if (accessor.builtGetter != null) {
kernel.nodeToAst[accessor.builtGetter] = node;
}
return result;
}
@override
@ -1740,7 +1755,7 @@ class KernelVisitor extends Object
SendSet node, LocalElement local, CompoundRhs rhs, _,
{bool isSetterValid}) {
ir.Expression compound =
buildCompound(new VariableAccessor(getLocal(local)), rhs);
buildCompound(new VariableAccessor(getLocal(local)), rhs, node);
if (compound is ir.VariableSet) {
associateNode(compound.value, node);
} else {
@ -2235,6 +2250,7 @@ class KernelVisitor extends Object
AssignmentOperator operator,
Node rhs,
_) {
// TODO(sra): Find binary operator.
return buildSuperIndexAccessor(index, getter, setter)
.buildCompoundAssignment(
kernel.irName(operator.selectorName, currentElement),
@ -2286,7 +2302,7 @@ class KernelVisitor extends Object
if (setterKind == CompoundSetter.INVALID) {
setter = null;
}
return buildCompound(buildSuperPropertyAccessor(getter, setter), rhs);
return buildCompound(buildSuperPropertyAccessor(getter, setter), rhs, node);
}
@override
@ -2301,13 +2317,14 @@ class KernelVisitor extends Object
if (setterKind == CompoundSetter.INVALID) {
setter = null;
}
return buildCompound(buildStaticAccessor(getter, setter), rhs);
return buildCompound(buildStaticAccessor(getter, setter), rhs, node);
}
@override
ir.Expression handleTypeLiteralConstantCompounds(
SendSet node, ConstantExpression constant, CompoundRhs rhs, _) {
return buildCompound(new ReadOnlyAccessor(buildTypeLiteral(constant)), rhs);
return buildCompound(
new ReadOnlyAccessor(buildTypeLiteral(constant)), rhs, node);
}
ir.TypeLiteral buildTypeVariable(TypeVariableElement element) {
@ -2317,7 +2334,8 @@ class KernelVisitor extends Object
@override
ir.Expression handleTypeVariableTypeLiteralCompounds(
SendSet node, TypeVariableElement element, CompoundRhs rhs, _) {
return buildCompound(new ReadOnlyAccessor(buildTypeVariable(element)), rhs);
return buildCompound(
new ReadOnlyAccessor(buildTypeVariable(element)), rhs, node);
}
@override

View file

@ -86,6 +86,9 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
LoopHandler<ir.Node> loopHandler;
TypeBuilder typeBuilder;
final Map<ir.VariableDeclaration, HInstruction> letBindings =
<ir.VariableDeclaration, HInstruction>{};
KernelSsaBuilder(
this.targetElement,
this.resolvedAst,
@ -939,10 +942,31 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
@override
void visitVariableGet(ir.VariableGet variableGet) {
ir.VariableDeclaration variable = variableGet.variable;
HInstruction letBinding = letBindings[variable];
if (letBinding != null) {
stack.add(letBinding);
return;
}
Local local = astAdapter.getLocal(variableGet.variable);
stack.add(localsHandler.readLocal(local));
}
@override
void visitPropertySet(ir.PropertySet propertySet) {
propertySet.receiver.accept(this);
HInstruction receiver = pop();
propertySet.value.accept(this);
HInstruction value = pop();
_pushDynamicInvocation(propertySet, astAdapter.typeOfSet(propertySet),
<HInstruction>[receiver, value]);
pop();
stack.add(value);
}
@override
void visitVariableSet(ir.VariableSet variableSet) {
variableSet.value.accept(this);
@ -984,6 +1008,16 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
value, astAdapter.getDartType(variable.type)));
}
@override
void visitLet(ir.Let let) {
ir.VariableDeclaration variable = let.variable;
variable.initializer.accept(this);
HInstruction initializedValue = pop();
// TODO(sra): Apply inferred type information.
letBindings[variable] = initializedValue;
let.body.accept(this);
}
// TODO(het): Also extract type arguments
/// Extracts the list of instructions for the expressions in the arguments.
List<HInstruction> _visitArguments(ir.Arguments arguments) {

View file

@ -96,7 +96,8 @@ class KernelAstAdapter {
ast.Node getNode(ir.Node node) {
ast.Node result = _nodeToAst[node];
assert(result != null);
assert(invariant(CURRENT_ELEMENT_SPANNABLE, result != null,
message: "No node found for $node"));
return result;
}
@ -144,6 +145,7 @@ class KernelAstAdapter {
Selector getSelector(ir.Expression node) {
if (node is ir.PropertyGet) return getGetterSelector(node);
if (node is ir.PropertySet) return getSetterSelector(node);
if (node is ir.InvocationExpression) return getInvocationSelector(node);
_compiler.reporter.internalError(getNode(node),
"Can only get the selector for a property get or an invocation.");
@ -174,7 +176,18 @@ class KernelAstAdapter {
return new Selector.getter(name);
}
Selector getSetterSelector(ir.PropertySet setter) {
ir.Name irName = setter.name;
Name name = new Name(
irName.name, irName.isPrivate ? getElement(irName.library) : null);
return new Selector.setter(name);
}
TypeMask typeOfInvocation(ir.Expression send) {
ast.Node operatorNode = kernel.nodeToAstOperator[send];
if (operatorNode != null) {
return _resultOf(_target).typeOfOperator(operatorNode);
}
return _resultOf(_target).typeOfSend(getNode(send));
}
@ -182,6 +195,10 @@ class KernelAstAdapter {
return _resultOf(_target).typeOfSend(getNode(getter));
}
TypeMask typeOfSet(ir.PropertySet setter) {
return _compiler.closedWorld.commonMasks.dynamicType;
}
TypeMask typeOfSend(ir.Expression send) {
assert(send is ir.InvocationExpression || send is ir.PropertyGet);
return _resultOf(_target).typeOfSend(getNode(send));

View file

@ -9,6 +9,13 @@ library kernel.frontend.accessors;
import '../ast.dart';
abstract class Accessor {
// [builtBinary] and [builtGetter] capture the inner nodes. Used by
// dart2js+rasta for determining how subexpressions map to legacy dart2js Ast
// nodes. This will be removed once dart2js type analysis (aka inference) is
// reimplemented on kernel.
Expression builtBinary;
Expression builtGetter;
Expression buildSimpleRead() {
return _finish(_makeSimpleRead());
}
@ -37,7 +44,8 @@ abstract class Accessor {
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{bool voidContext: false, Procedure interfaceTarget}) {
return _finish(_makeWrite(
makeBinary(_makeRead(), binaryOperator, interfaceTarget, value),
builtBinary =
makeBinary(_makeRead(), binaryOperator, interfaceTarget, value),
voidContext));
}
@ -56,7 +64,7 @@ abstract class Accessor {
var value = new VariableDeclaration.forValue(_makeRead());
valueAccess() => new VariableGet(value);
var dummy = new VariableDeclaration.forValue(_makeWrite(
makeBinary(
builtBinary = makeBinary(
valueAccess(), binaryOperator, interfaceTarget, new IntLiteral(1)),
true));
return _finish(makeLet(value, makeLet(dummy, valueAccess())));
@ -122,7 +130,7 @@ class PropertyAccessor extends Accessor {
return new VariableGet(_receiverVariable);
}
_makeRead() => new PropertyGet(receiverAccess(), name, getter);
_makeRead() => builtGetter = new PropertyGet(receiverAccess(), name, getter);
_makeWrite(Expression value, bool voidContext) {
return new PropertySet(receiverAccess(), name, value, setter);
@ -139,7 +147,8 @@ class ThisPropertyAccessor extends Accessor {
ThisPropertyAccessor(this.name, this.getter, this.setter);
_makeRead() => new PropertyGet(new ThisExpression(), name, getter);
_makeRead() =>
builtGetter = new PropertyGet(new ThisExpression(), name, getter);
_makeWrite(Expression value, bool voidContext) {
return new PropertySet(new ThisExpression(), name, value, setter);
@ -158,7 +167,7 @@ class NullAwarePropertyAccessor extends Accessor {
receiverAccess() => new VariableGet(receiver);
_makeRead() => new PropertyGet(receiverAccess(), name, getter);
_makeRead() => builtGetter = new PropertyGet(receiverAccess(), name, getter);
_makeWrite(Expression value, bool voidContext) {
return new PropertySet(receiverAccess(), name, value, setter);