1
0
mirror of https://github.com/dart-lang/sdk synced 2024-07-05 09:20:04 +00:00

Generated source mapping through CPS.

BUG=
R=karlklose@google.com

Review URL: https://codereview.chromium.org//1229673006.
This commit is contained in:
Johnni Winther 2015-07-10 15:32:36 +02:00
parent 9a7d77604b
commit 73572dc3f1
15 changed files with 522 additions and 188 deletions

View File

@ -624,12 +624,13 @@ class IrBuilder {
ir.Primitive _buildInvokeSuper(Element target,
Selector selector,
List<ir.Primitive> arguments) {
List<ir.Primitive> arguments,
SourceInformation sourceInformation) {
assert(target.isInstanceMember);
assert(isOpen);
return _continueWithExpression(
(k) => new ir.InvokeMethodDirectly(
buildThis(), target, selector, arguments, k));
buildThis(), target, selector, arguments, k, sourceInformation));
}
ir.Primitive _buildInvokeDynamic(ir.Primitive receiver,
@ -655,9 +656,11 @@ class IrBuilder {
/// Create a [ir.Constant] from [value] and add it to the CPS term.
ir.Constant buildConstant(ConstantValue value) {
ir.Constant buildConstant(ConstantValue value,
{SourceInformation sourceInformation}) {
assert(isOpen);
return addPrimitive(new ir.Constant(value));
return addPrimitive(
new ir.Constant(value, sourceInformation: sourceInformation));
}
/// Create an integer constant and add it to the CPS term.
@ -793,63 +796,74 @@ class IrBuilder {
/// Create a invocation of the [method] on the super class where the call
/// structure is defined [callStructure] and the argument values are defined
/// by [arguments].
ir.Primitive buildSuperMethodInvocation(MethodElement method,
CallStructure callStructure,
List<ir.Primitive> arguments) {
ir.Primitive buildSuperMethodInvocation(
MethodElement method,
CallStructure callStructure,
List<ir.Primitive> arguments,
{SourceInformation sourceInformation}) {
// TODO(johnniwinther): This shouldn't be necessary.
SelectorKind kind = Elements.isOperatorName(method.name)
? SelectorKind.OPERATOR : SelectorKind.CALL;
Selector selector =
new Selector(kind, method.memberName, callStructure);
return _buildInvokeSuper(method, selector, arguments);
return _buildInvokeSuper(method, selector, arguments, sourceInformation);
}
/// Create a read access of the [method] on the super class, i.e. a
/// closurization of [method].
ir.Primitive buildSuperMethodGet(MethodElement method) {
ir.Primitive buildSuperMethodGet(MethodElement method,
{SourceInformation sourceInformation}) {
// TODO(johnniwinther): This should have its own ir node.
return _buildInvokeSuper(
method,
new Selector.getter(method.name, method.library),
const <ir.Primitive>[]);
const <ir.Primitive>[],
sourceInformation);
}
/// Create a getter invocation of the [getter] on the super class.
ir.Primitive buildSuperGetterGet(MethodElement getter) {
ir.Primitive buildSuperGetterGet(MethodElement getter,
SourceInformation sourceInformation) {
// TODO(johnniwinther): This should have its own ir node.
return _buildInvokeSuper(
getter,
new Selector.getter(getter.name, getter.library),
const <ir.Primitive>[]);
const <ir.Primitive>[],
sourceInformation);
}
/// Create an setter invocation of the [setter] on the super class with
/// [value].
ir.Primitive buildSuperSetterSet(MethodElement setter,
ir.Primitive value) {
ir.Primitive value,
{SourceInformation sourceInformation}) {
// TODO(johnniwinther): This should have its own ir node.
_buildInvokeSuper(
setter,
new Selector.setter(setter.name, setter.library),
<ir.Primitive>[value]);
<ir.Primitive>[value],
sourceInformation);
return value;
}
/// Create an invocation of the index [method] on the super class with
/// the provided [index].
ir.Primitive buildSuperIndex(MethodElement method,
ir.Primitive index) {
ir.Primitive index,
{SourceInformation sourceInformation}) {
return _buildInvokeSuper(
method, new Selector.index(), <ir.Primitive>[index]);
method, new Selector.index(), <ir.Primitive>[index],
sourceInformation);
}
/// Create an invocation of the index set [method] on the super class with
/// the provided [index] and [value].
ir.Primitive buildSuperIndexSet(MethodElement method,
ir.Primitive index,
ir.Primitive value) {
ir.Primitive value,
{SourceInformation sourceInformation}) {
_buildInvokeSuper(method, new Selector.indexSet(),
<ir.Primitive>[index, value]);
<ir.Primitive>[index, value], sourceInformation);
return value;
}
@ -859,8 +873,11 @@ class IrBuilder {
ir.Primitive buildDynamicInvocation(ir.Primitive receiver,
Selector selector,
TypeMask mask,
List<ir.Primitive> arguments) {
return _buildInvokeDynamic(receiver, selector, mask, arguments);
List<ir.Primitive> arguments,
{SourceInformation sourceInformation}) {
return _buildInvokeDynamic(
receiver, selector, mask, arguments,
sourceInformation: sourceInformation);
}
/// Create a dynamic getter invocation on [receiver] where the getter name is
@ -925,11 +942,14 @@ class IrBuilder {
/// Create an invocation of the the [local] variable or parameter where
/// argument structure is defined by [callStructure] and the argument values
/// are defined by [arguments].
ir.Primitive buildLocalVariableInvocation(LocalVariableElement local,
CallStructure callStructure,
List<ir.Primitive> arguments) {
ir.Primitive buildLocalVariableInvocation(
LocalVariableElement local,
CallStructure callStructure,
List<ir.Primitive> arguments,
{SourceInformation callSourceInformation}) {
return buildCallInvocation(
buildLocalVariableGet(local), callStructure, arguments);
buildLocalVariableGet(local), callStructure, arguments,
sourceInformation: callSourceInformation);
}
/// Create an invocation of the local [function] where argument structure is
@ -938,10 +958,12 @@ class IrBuilder {
ir.Primitive buildLocalFunctionInvocation(
LocalFunctionElement function,
CallStructure callStructure,
List<ir.Primitive> arguments) {
List<ir.Primitive> arguments,
SourceInformation sourceInformation) {
// TODO(johnniwinther): Maybe this should have its own ir node.
return buildCallInvocation(
buildLocalFunctionGet(function), callStructure, arguments);
buildLocalFunctionGet(function), callStructure, arguments,
sourceInformation: sourceInformation);
}
/// Create a static invocation of [function] where argument structure is
@ -974,7 +996,7 @@ class IrBuilder {
/// Create a getter invocation of the static [getter].
ir.Primitive buildStaticGetterGet(MethodElement getter,
{SourceInformation sourceInformation}) {
SourceInformation sourceInformation) {
Selector selector = new Selector.getter(getter.name, getter.library);
return _buildInvokeStatic(
getter, selector, const <ir.Primitive>[], sourceInformation);
@ -1958,7 +1980,7 @@ class IrBuilder {
IrBuilder builder = makeDelimitedBuilder(newReturn.environment);
ir.Primitive value = builder.environment.discard(1);
buildFinallyBlock(builder);
if (builder.isOpen) builder.buildReturn(value);
if (builder.isOpen) builder.buildReturn(value: value);
newReturn.continuation.body = builder._root;
exits.add(newReturn.continuation);
}
@ -1973,7 +1995,7 @@ class IrBuilder {
/// Create a return statement `return value;` or `return;` if [value] is
/// null.
void buildReturn([ir.Primitive value]) {
void buildReturn({ir.Primitive value, SourceInformation sourceInformation}) {
// Build(Return(e), C) = C'[InvokeContinuation(return, x)]
// where (C', x) = Build(e, C)
//
@ -1983,7 +2005,8 @@ class IrBuilder {
value = buildNullConstant();
}
if (state.returnCollector == null) {
add(new ir.InvokeContinuation(state.returnContinuation, [value]));
add(new ir.InvokeContinuation(state.returnContinuation, [value],
sourceInformation: sourceInformation));
_current = null;
} else {
// Inside the try block of try/finally, all returns go to a join-point
@ -2305,12 +2328,15 @@ class IrBuilder {
/// Add [functionElement] to the environment with provided [definition].
void declareLocalFunction(LocalFunctionElement functionElement,
ClosureClassElement classElement) {
ir.Primitive closure = buildFunctionExpression(classElement);
ClosureClassElement classElement,
SourceInformation sourceInformation) {
ir.Primitive closure =
buildFunctionExpression(classElement, sourceInformation);
declareLocalVariable(functionElement, initialValue: closure);
}
ir.Primitive buildFunctionExpression(ClosureClassElement classElement) {
ir.Primitive buildFunctionExpression(ClosureClassElement classElement,
SourceInformation sourceInformation) {
List<ir.Primitive> arguments = <ir.Primitive>[];
for (ClosureFieldElement field in classElement.closureFields) {
// Captured 'this' is not available as a local in the current environment,
@ -2320,8 +2346,8 @@ class IrBuilder {
: environment.lookup(field.local);
arguments.add(value);
}
return addPrimitive(
new ir.CreateInstance(classElement, arguments, const <ir.Primitive>[]));
return addPrimitive(new ir.CreateInstance(
classElement, arguments, const <ir.Primitive>[], sourceInformation));
}
/// Create a read access of [local] variable or parameter.
@ -2430,13 +2456,14 @@ class IrBuilder {
ir.Primitive buildInvokeDirectly(FunctionElement target,
ir.Primitive receiver,
List<ir.Primitive> arguments) {
List<ir.Primitive> arguments,
{SourceInformation sourceInformation}) {
assert(isOpen);
Selector selector =
new Selector.call(target.name, target.library, arguments.length);
return _continueWithExpression(
(k) => new ir.InvokeMethodDirectly(
receiver, target, selector, arguments, k));
receiver, target, selector, arguments, k, sourceInformation));
}
/// Loads parameters to a constructor body into the environment.
@ -2459,10 +2486,12 @@ class IrBuilder {
/// Create a constructor invocation of [element] on [type] where the
/// constructor name and argument structure are defined by [callStructure] and
/// the argument values are defined by [arguments].
ir.Primitive buildConstructorInvocation(ConstructorElement element,
CallStructure callStructure,
DartType type,
List<ir.Primitive> arguments) {
ir.Primitive buildConstructorInvocation(
ConstructorElement element,
CallStructure callStructure,
DartType type,
List<ir.Primitive> arguments,
SourceInformation sourceInformation) {
assert(isOpen);
Selector selector =
new Selector(SelectorKind.CALL, element.memberName, callStructure);
@ -2479,8 +2508,8 @@ class IrBuilder {
..addAll(typeArguments);
}
return _continueWithExpression(
(k) => new ir.InvokeConstructor(type, element, selector,
arguments, k));
(k) => new ir.InvokeConstructor(
type, element, selector, arguments, k, sourceInformation));
}
ir.Primitive buildTypeExpression(DartType type) {
@ -2508,7 +2537,8 @@ class IrBuilder {
/// if we are currently building a constructor field initializer, from the
/// corresponding type argument (field initializers are evaluated before the
/// receiver object is created).
ir.Primitive buildTypeVariableAccess(TypeVariableType variable) {
ir.Primitive buildTypeVariableAccess(TypeVariableType variable,
{SourceInformation sourceInformation}) {
// If the local exists in the environment, use that.
// This is put here when we are inside a constructor or field initializer,
// (or possibly a closure inside one of these).
@ -2520,7 +2550,8 @@ class IrBuilder {
// If the type variable is not in a local, read its value from the
// receiver object.
ir.Primitive target = buildThis();
return addPrimitive(new ir.ReadTypeVariable(variable, target));
return addPrimitive(
new ir.ReadTypeVariable(variable, target, sourceInformation));
}
/// Make the given type variable accessible through the local environment
@ -2532,9 +2563,12 @@ class IrBuilder {
}
/// Reifies the value of [variable] on the current receiver object.
ir.Primitive buildReifyTypeVariable(TypeVariableType variable) {
ir.Primitive typeArgument = buildTypeVariableAccess(variable);
return addPrimitive(new ir.ReifyRuntimeType(typeArgument));
ir.Primitive buildReifyTypeVariable(TypeVariableType variable,
SourceInformation sourceInformation) {
ir.Primitive typeArgument =
buildTypeVariableAccess(variable, sourceInformation: sourceInformation);
return addPrimitive(
new ir.ReifyRuntimeType(typeArgument, sourceInformation));
}
ir.Primitive buildInvocationMirror(Selector selector,

View File

@ -284,8 +284,11 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
targetConstructor,
callStructure,
targetType,
arguments);
irBuilder.buildReturn(instance);
arguments,
sourceInformationBuilder.buildNew(node));
irBuilder.buildReturn(
value: instance,
sourceInformation: sourceInformationBuilder.buildReturn(node));
}
visitFor(ast.For node) {
@ -399,7 +402,9 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
ir.Primitive visitReturn(ast.Return node) {
assert(irBuilder.isOpen);
assert(invariant(node, node.beginToken.value != 'native'));
irBuilder.buildReturn(build(node.expression));
irBuilder.buildReturn(
value: build(node.expression),
sourceInformation: sourceInformationBuilder.buildReturn(node));
return null;
}
@ -533,9 +538,11 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
return irBuilder.state.constants.getConstantValueForVariable(element);
}
ir.Primitive buildConstantExpression(ConstantExpression expression) {
ir.Primitive buildConstantExpression(ConstantExpression expression,
SourceInformation sourceInformation) {
return irBuilder.buildConstant(
irBuilder.state.constants.getConstantValue(expression));
irBuilder.state.constants.getConstantValue(expression),
sourceInformation: sourceInformation);
}
ir.Primitive visitLiteralList(ast.LiteralList node) {
@ -599,7 +606,7 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
} else {
// The call to assert and its argument expression must be ignored
// in production mode.
// Assertions can only occur in expression statements, so no value needs
// Assertions can onl)y occur in expression statements, so no value needs
// to be returned.
return null;
}
@ -613,13 +620,15 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
@override
ir.Primitive visitExpressionInvoke(ast.Send node,
ast.Node expression,
ast.NodeList arguments,
ast.NodeList argumentsNode,
Selector selector, _) {
ir.Primitive receiver = visit(expression);
List<ir.Primitive> arguments = node.arguments.mapToList(visit);
arguments = normalizeDynamicArguments(selector.callStructure, arguments);
return irBuilder.buildCallInvocation(
receiver, selector.callStructure, arguments);
receiver, selector.callStructure, arguments,
sourceInformation:
sourceInformationBuilder.buildCall(node, argumentsNode));
}
/// Returns `true` if [node] is a super call.
@ -632,7 +641,8 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
ir.Primitive handleConstantGet(
ast.Node node,
ConstantExpression constant, _) {
return buildConstantExpression(constant);
return buildConstantExpression(constant,
sourceInformationBuilder.buildGet(node));
}
/// If [node] is null, returns this.
@ -671,7 +681,8 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
ast.Send node,
ConstantExpression constant,
_) {
return buildConstantExpression(constant);
return buildConstantExpression(constant,
sourceInformationBuilder.buildGet(node));
}
@override
@ -680,7 +691,8 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
LocalVariableElement element,
_) {
return element.isConst
? irBuilder.buildConstant(getConstantForVariable(element))
? irBuilder.buildConstant(getConstantForVariable(element),
sourceInformation: sourceInformationBuilder.buildGet(node))
: irBuilder.buildLocalVariableGet(element);
}
@ -717,7 +729,8 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
ast.Send node,
FunctionElement getter,
_) {
return irBuilder.buildStaticGetterGet(getter);
return irBuilder.buildStaticGetterGet(
getter, sourceInformationBuilder.buildGet(node));
}
@override
@ -733,7 +746,8 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
ast.Send node,
FunctionElement getter,
_) {
return irBuilder.buildSuperGetterGet(getter);
return irBuilder.buildSuperGetterGet(
getter, sourceInformationBuilder.buildGet(node));
}
@override
@ -763,14 +777,17 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
return irBuilder.buildThis();
}
ir.Primitive translateTypeVariableTypeLiteral(TypeVariableElement element) {
return irBuilder.buildReifyTypeVariable(element.type);
ir.Primitive translateTypeVariableTypeLiteral(
TypeVariableElement element,
SourceInformation sourceInformation) {
return irBuilder.buildReifyTypeVariable(element.type, sourceInformation);
}
@override
ir.Primitive visitTypeVariableTypeLiteralGet(ast.Send node,
TypeVariableElement element, _) {
return translateTypeVariableTypeLiteral(element);
return translateTypeVariableTypeLiteral(element,
sourceInformationBuilder.buildGet(node));
}
ir.Primitive translateLogicalOperator(ast.Expression left,
@ -842,7 +859,9 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
List<ir.Primitive> arguments = <ir.Primitive>[visit(right)];
arguments = normalizeDynamicArguments(selector.callStructure, arguments);
return irBuilder.buildDynamicInvocation(
receiver, selector, elements.getTypeMask(node), arguments);
receiver, selector, elements.getTypeMask(node), arguments,
sourceInformation:
sourceInformationBuilder.buildCall(node, node.selector));
}
@override
@ -979,10 +998,12 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
ir.Primitive translateCallInvoke(ir.Primitive target,
ast.NodeList arguments,
CallStructure callStructure) {
CallStructure callStructure,
SourceInformation sourceInformation) {
return irBuilder.buildCallInvocation(target, callStructure,
translateDynamicArguments(arguments, callStructure));
translateDynamicArguments(arguments, callStructure),
sourceInformation: sourceInformation);
}
@override
@ -992,8 +1013,10 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
ast.NodeList arguments,
CallStructure callStructure,
_) {
ir.Primitive target = buildConstantExpression(constant);
return translateCallInvoke(target, arguments, callStructure);
ir.Primitive target = buildConstantExpression(constant,
sourceInformationBuilder.buildGet(node));
return translateCallInvoke(target, arguments, callStructure,
sourceInformationBuilder.buildCall(node, arguments));
}
@override
@ -1005,7 +1028,9 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
_) {
return irBuilder.buildDynamicInvocation(
translateReceiver(receiver), selector, elements.getTypeMask(node),
translateDynamicArguments(arguments, selector.callStructure));
translateDynamicArguments(arguments, selector.callStructure),
sourceInformation:
sourceInformationBuilder.buildCall(node, node.selector));
}
@override
@ -1030,7 +1055,9 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
CallStructure callStructure,
_) {
return irBuilder.buildLocalVariableInvocation(element, callStructure,
translateDynamicArguments(arguments, callStructure));
translateDynamicArguments(arguments, callStructure),
callSourceInformation:
sourceInformationBuilder.buildCall(node, arguments));
}
@override
@ -1041,7 +1068,8 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
CallStructure callStructure,
_) {
return irBuilder.buildLocalFunctionInvocation(function, callStructure,
translateDynamicArguments(arguments, callStructure));
translateDynamicArguments(arguments, callStructure),
sourceInformationBuilder.buildCall(node, arguments));
}
@override
@ -1060,7 +1088,9 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
ir.Primitive target = buildStaticFieldGet(field, src);
return irBuilder.buildCallInvocation(target,
callStructure,
translateDynamicArguments(arguments, callStructure));
translateDynamicArguments(arguments, callStructure),
sourceInformation:
sourceInformationBuilder.buildCall(node, arguments));
}
@override
@ -1092,10 +1122,13 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
if (compiler.backend.isForeign(getter)) {
return giveup(node, 'handleStaticGetterInvoke: foreign: $getter');
}
ir.Primitive target = irBuilder.buildStaticGetterGet(getter);
ir.Primitive target = irBuilder.buildStaticGetterGet(
getter, sourceInformationBuilder.buildGet(node));
return irBuilder.buildCallInvocation(target,
callStructure,
translateDynamicArguments(arguments, callStructure));
translateDynamicArguments(arguments, callStructure),
sourceInformation:
sourceInformationBuilder.buildCall(node, arguments));
}
@override
@ -1108,7 +1141,9 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
ir.Primitive target = irBuilder.buildSuperFieldGet(field);
return irBuilder.buildCallInvocation(target,
callStructure,
translateDynamicArguments(arguments, callStructure));
translateDynamicArguments(arguments, callStructure),
sourceInformation:
sourceInformationBuilder.buildCall(node, arguments));
}
@override
@ -1118,10 +1153,13 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
ast.NodeList arguments,
CallStructure callStructure,
_) {
ir.Primitive target = irBuilder.buildSuperGetterGet(getter);
ir.Primitive target = irBuilder.buildSuperGetterGet(
getter, sourceInformationBuilder.buildGet(node));
return irBuilder.buildCallInvocation(target,
callStructure,
translateDynamicArguments(arguments, callStructure));
translateDynamicArguments(arguments, callStructure),
sourceInformation:
sourceInformationBuilder.buildCall(node, arguments));
}
@override
@ -1132,7 +1170,9 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
CallStructure callStructure,
_) {
return irBuilder.buildSuperMethodInvocation(method, callStructure,
translateDynamicArguments(arguments, callStructure));
translateDynamicArguments(arguments, callStructure),
sourceInformation:
sourceInformationBuilder.buildCall(node, node.selector));
}
@override
@ -1165,7 +1205,11 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
ast.NodeList arguments,
CallStructure callStructure,
_) {
return translateCallInvoke(irBuilder.buildThis(), arguments, callStructure);
return translateCallInvoke(
irBuilder.buildThis(),
arguments,
callStructure,
sourceInformationBuilder.buildCall(node, arguments));
}
@override
@ -1176,9 +1220,11 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
CallStructure callStructure,
_) {
return translateCallInvoke(
translateTypeVariableTypeLiteral(element),
translateTypeVariableTypeLiteral(
element, sourceInformationBuilder.buildGet(node)),
arguments,
callStructure);
callStructure,
sourceInformationBuilder.buildCall(node, arguments));
}
@override
@ -1327,7 +1373,10 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
CompoundRhs rhs,
arg) {
return translateCompounds(
getValue: () => buildConstantExpression(constant),
getValue: () {
return buildConstantExpression(constant,
sourceInformationBuilder.buildGet(node));
},
rhs: rhs,
setValue: (value) {}, // The binary operator will throw before this.
operatorTypeMask: elements.getOperatorTypeMaskInComplexSendSet(node));
@ -1419,7 +1468,8 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
SourceInformation src = sourceInformationBuilder.buildGet(node);
return irBuilder.buildStaticFieldGet(getter, src);
case CompoundGetter.GETTER:
return irBuilder.buildStaticGetterGet(getter);
return irBuilder.buildStaticGetterGet(
getter, sourceInformationBuilder.buildGet(node));
case CompoundGetter.METHOD:
return irBuilder.buildStaticFunctionGet(getter);
case CompoundGetter.UNRESOLVED:
@ -1473,7 +1523,8 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
case CompoundGetter.FIELD:
return irBuilder.buildSuperFieldGet(getter);
case CompoundGetter.GETTER:
return irBuilder.buildSuperGetterGet(getter);
return irBuilder.buildSuperGetterGet(
getter, sourceInformationBuilder.buildGet(node));
case CompoundGetter.METHOD:
return irBuilder.buildSuperMethodGet(getter);
case CompoundGetter.UNRESOLVED:
@ -1505,7 +1556,11 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
CompoundRhs rhs,
arg) {
return translateCompounds(
getValue: () => irBuilder.buildReifyTypeVariable(typeVariable.type),
getValue: () {
return irBuilder.buildReifyTypeVariable(
typeVariable.type,
sourceInformationBuilder.buildGet(node));
},
rhs: rhs,
setValue: (value) {}, // The binary operator will throw before this.
operatorTypeMask: elements.getOperatorTypeMaskInComplexSendSet(node));
@ -1621,7 +1676,9 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
ir.Primitive translateConstant(ast.Node node) {
assert(irBuilder.isOpen);
return irBuilder.buildConstant(getConstantForNode(node));
return irBuilder.buildConstant(
getConstantForNode(node),
sourceInformation: sourceInformationBuilder.buildGet(node));
}
ir.Primitive visitThrow(ast.Throw node) {
@ -2255,13 +2312,15 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
}
ir.Primitive visitFunctionExpression(ast.FunctionExpression node) {
return irBuilder.buildFunctionExpression(makeSubFunction(node));
return irBuilder.buildFunctionExpression(makeSubFunction(node),
sourceInformationBuilder.buildCreate(node));
}
visitFunctionDeclaration(ast.FunctionDeclaration node) {
LocalFunctionElement element = elements[node.function];
Object inner = makeSubFunction(node.function);
irBuilder.declareLocalFunction(element, inner);
irBuilder.declareLocalFunction(element, inner,
sourceInformationBuilder.buildCreate(node.function));
}
Map mapValues(Map map, dynamic fn(dynamic)) {
@ -2376,7 +2435,12 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
return withBuilder(builder, () {
irBuilder.buildFunctionHeader(<Local>[]);
ir.Primitive initialValue = visit(element.initializer);
irBuilder.buildReturn(initialValue);
ast.VariableDefinitions node = element.node;
ast.SendSet sendSet = node.definitions.nodes.head;
irBuilder.buildReturn(
value: initialValue,
sourceInformation:
sourceInformationBuilder.buildReturn(sendSet.assignmentOperator));
return irBuilder.makeFunctionDefinition();
});
}
@ -2501,10 +2565,16 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
// Native fields are initialized elsewhere.
}
}, includeSuperAndInjectedMembers: true);
ir.Primitive instance = new ir.CreateInstance(
classElement,
instanceArguments,
typeInformation);
typeInformation,
constructor.hasNode
? sourceInformationBuilder.buildCreate(constructor.node)
// TODO(johnniwinther): Provide source information for creation
// through synthetic constructors.
: null);
irBuilder.add(new ir.LetPrim(instance));
// --- Call constructor bodies ---
@ -2519,7 +2589,10 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
}
// --- step 4: return the created object ----
irBuilder.buildReturn(instance);
irBuilder.buildReturn(
value: instance,
sourceInformation:
sourceInformationBuilder.buildImplicitReturn(constructor));
return irBuilder.makeFunctionDefinition();
});
@ -2974,7 +3047,8 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
target,
callStructure,
constructor.computeEffectiveTargetType(type),
arguments);
arguments,
sourceInformationBuilder.buildNew(node));
}
@override
@ -3027,7 +3101,7 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
ir.Primitive buildStaticFieldGet(FieldElement field, SourceInformation src) {
ConstantValue constant = getConstantForVariable(field);
if (constant != null && !field.isAssignable) {
return irBuilder.buildConstant(constant);
return irBuilder.buildConstant(constant, sourceInformation: src);
} else if (backend.constants.lazyStatics.contains(field)) {
return irBuilder.buildStaticFieldLazyGet(field, src);
} else {

View File

@ -344,12 +344,14 @@ class InvokeMethodDirectly extends Expression implements Invoke {
final Selector selector;
final List<Reference<Primitive>> arguments;
final Reference<Continuation> continuation;
final SourceInformation sourceInformation;
InvokeMethodDirectly(Primitive receiver,
this.target,
this.selector,
List<Primitive> arguments,
Continuation continuation)
Continuation continuation,
this.sourceInformation)
: this.receiver = new Reference<Primitive>(receiver),
this.arguments = _referenceList(arguments),
this.continuation = new Reference<Continuation>(continuation);
@ -378,12 +380,14 @@ class InvokeConstructor extends Expression implements Invoke {
final List<Reference<Primitive>> arguments;
final Reference<Continuation> continuation;
final Selector selector;
final SourceInformation sourceInformation;
InvokeConstructor(this.type,
this.target,
this.selector,
List<Primitive> args,
Continuation cont)
Continuation cont,
this.sourceInformation)
: arguments = _referenceList(args),
continuation = new Reference<Continuation>(cont);
@ -563,6 +567,7 @@ class SetMutableVariable extends Expression implements InteriorNode {
class InvokeContinuation extends Expression {
Reference<Continuation> continuation;
List<Reference<Primitive>> arguments;
SourceInformation sourceInformation;
// An invocation of a continuation is recursive if it occurs in the body of
// the continuation itself.
@ -574,7 +579,8 @@ class InvokeContinuation extends Expression {
InvokeContinuation(Continuation cont, List<Primitive> args,
{this.isRecursive: false,
this.isEscapingTry: false})
this.isEscapingTry: false,
this.sourceInformation})
: continuation = new Reference<Continuation>(cont),
arguments = _referenceList(args) {
assert(cont.parameters == null || cont.parameters.length == args.length);
@ -586,10 +592,11 @@ class InvokeContinuation extends Expression {
///
/// Used as a placeholder for a jump whose target is not yet created
/// (e.g., in the translation of break and continue).
InvokeContinuation.uninitialized({this.isRecursive: false,
InvokeContinuation.uninitialized({this.isRecursive: false,
this.isEscapingTry: false})
: continuation = null,
arguments = null;
arguments = null,
sourceInformation = null;
accept(Visitor visitor) => visitor.visitInvokeContinuation(this);
}
@ -798,8 +805,11 @@ class CreateInstance extends Primitive {
/// is not needed at runtime.
final List<Reference<Primitive>> typeInformation;
final SourceInformation sourceInformation;
CreateInstance(this.classElement, List<Primitive> arguments,
List<Primitive> typeInformation)
List<Primitive> typeInformation,
this.sourceInformation)
: this.arguments = _referenceList(arguments),
this.typeInformation = _referenceList(typeInformation);
@ -856,8 +866,9 @@ class ForeignCode extends Expression {
class Constant extends Primitive {
final values.ConstantValue value;
final SourceInformation sourceInformation;
Constant(this.value);
Constant(this.value, {this.sourceInformation});
accept(Visitor visitor) => visitor.visitConstant(this);
@ -959,7 +970,7 @@ class Continuation extends Definition<Continuation> implements InteriorNode {
Continuation(this.parameters, {this.isRecursive: false});
Continuation.retrn()
Continuation.retrn()
: parameters = <Parameter>[new Parameter(null)],
isRecursive = false;
@ -1001,7 +1012,10 @@ class ReifyRuntimeType extends Primitive {
/// Reference to the internal representation of a type (as produced, for
/// example, by [ReadTypeVariable]).
final Reference<Primitive> value;
ReifyRuntimeType(Primitive value)
final SourceInformation sourceInformation;
ReifyRuntimeType(Primitive value, this.sourceInformation)
: this.value = new Reference<Primitive>(value);
@override
@ -1019,8 +1033,9 @@ class ReifyRuntimeType extends Primitive {
class ReadTypeVariable extends Primitive {
final TypeVariableType variable;
final Reference<Primitive> target;
final SourceInformation sourceInformation;
ReadTypeVariable(this.variable, Primitive target)
ReadTypeVariable(this.variable, Primitive target, this.sourceInformation)
: this.target = new Reference<Primitive>(target);
@override

View File

@ -93,3 +93,52 @@ _reportHere(Compiler compiler, Spannable node, String debugMessage) {
compiler.reportInfo(node,
MessageKind.GENERIC, {'text': 'HERE: $debugMessage'});
}
/// Set of tracked objects used by [track] and [ifTracked].
var _trackedObjects = new Set();
/// Global default value for the `printTrace` option of [track] and [ifTracked].
bool trackWithTrace = false;
/// If [doTrack] is `true`, add [object] to the set of tracked objects.
///
/// If tracked, [message] is printed along the hash code and toString of
/// [object]. If [printTrace] is `true` a trace printed additionally.
/// If [printTrace] is `null`, [trackWithTrace] determines whether a trace is
/// printed.
///
/// [object] is returned as the result of the method.
track(bool doTrack, Object object, String message, {bool printTrace}) {
if (!doTrack) return object;
_trackedObjects.add(object);
String msg = 'track: ${object.hashCode}:$object:$message';
if (printTrace == null) printTrace = trackWithTrace;
if (printTrace) {
trace(msg);
} else {
debugPrint(msg);
}
return object;
}
/// Returns `true` if [object] is in the set of tracked objects.
///
/// If [message] is provided it is printed along the hash code and toString of
/// [object]. If [printTrace] is `true` a trace printed additionally. If
/// [printTrace] is `null`, [trackWithTrace] determines whether a trace is
/// printed.
bool ifTracked(Object object, {String message, bool printTrace}) {
if (_trackedObjects.contains(object)) {
if (message != null) {
String msg = 'tracked: ${object.hashCode}:$object:$message';
if (printTrace == null) printTrace = trackWithTrace;
if (printTrace) {
trace(msg);
} else {
debugPrint(msg);
}
}
return true;
}
return false;
}

View File

@ -148,6 +148,9 @@ class PositionSourceInformationBuilder implements SourceInformationBuilder {
@override
SourceInformation buildGeneric(Node node) => buildBegin(node);
@override
SourceInformation buildCreate(Node node) => buildBegin(node);
@override
SourceInformation buildReturn(Node node) => buildBegin(node);

View File

@ -61,6 +61,10 @@ class SourceInformationBuilder {
@deprecated
SourceInformation buildGeneric(Node node) => null;
/// Generate [SourceInformation] for an instantiation of a class using [node]
/// for the source position.
SourceInformation buildCreate(Node node) => null;
/// Generate [SourceInformation] for the return [node].
SourceInformation buildReturn(Node node) => null;

View File

@ -203,9 +203,10 @@ class StartEndSourceInformationBuilder extends SourceInformationBuilder {
}
@override
SourceInformation buildReturn(Node node) {
return buildGeneric(node);
}
SourceInformation buildCreate(Node node) => buildGeneric(node);
@override
SourceInformation buildReturn(Node node) => buildGeneric(node);
@override
SourceInformation buildGet(Node node) => buildGeneric(node);

View File

@ -51,7 +51,7 @@ class CodeGenerator extends tree_ir.StatementVisitor
/// Stacks whose top element is the current target of an unlabeled break
/// or continue. For continues, this is the loop node itself.
final tree_ir.FallthroughStack shortBreak = new tree_ir.FallthroughStack();
final tree_ir.FallthroughStack shortContinue =
final tree_ir.FallthroughStack shortContinue =
new tree_ir.FallthroughStack();
Set<tree_ir.Label> usedLabels = new Set<tree_ir.Label>();
@ -183,14 +183,18 @@ class CodeGenerator extends tree_ir.StatementVisitor
visitExpression(node.elseExpression));
}
js.Expression buildConstant(ConstantValue constant) {
js.Expression buildConstant(ConstantValue constant,
{SourceInformation sourceInformation}) {
registry.registerCompileTimeConstant(constant);
return glue.constantReference(constant);
return glue.constantReference(constant)
.withSourceInformation(sourceInformation);
}
@override
js.Expression visitConstant(tree_ir.Constant node) {
return buildConstant(node.value);
return buildConstant(
node.value,
sourceInformation: node.sourceInformation);
}
js.Expression compileConstant(ParameterElement parameter) {
@ -213,7 +217,8 @@ class CodeGenerator extends tree_ir.StatementVisitor
registry.registerInstantiatedType(node.type);
FunctionElement target = node.target;
List<js.Expression> arguments = visitExpressionList(node.arguments);
return buildStaticInvoke(target, arguments);
return buildStaticInvoke(
target, arguments, sourceInformation: node.sourceInformation);
}
void registerMethodInvoke(tree_ir.InvokeMethod node) {
@ -240,7 +245,8 @@ class CodeGenerator extends tree_ir.StatementVisitor
registerMethodInvoke(node);
return js.propertyCall(visitExpression(node.receiver),
glue.invocationName(node.selector),
visitExpressionList(node.arguments));
visitExpressionList(node.arguments))
.withSourceInformation(node.sourceInformation);
}
@override
@ -260,13 +266,15 @@ class CodeGenerator extends tree_ir.StatementVisitor
return js.js('#.#(#)',
[visitExpression(node.receiver),
glue.instanceMethodName(node.target),
visitExpressionList(node.arguments)]);
visitExpressionList(node.arguments)])
.withSourceInformation(node.sourceInformation);
}
return js.js('#.#.call(#, #)',
[glue.prototypeAccess(node.target.enclosingClass),
glue.invocationName(node.selector),
visitExpression(node.receiver),
visitExpressionList(node.arguments)]);
visitExpressionList(node.arguments)])
.withSourceInformation(node.sourceInformation);
}
@override
@ -425,7 +433,7 @@ class CodeGenerator extends tree_ir.StatementVisitor
} else if (isEffectiveBreakTarget(node, shortBreak.target)) {
// Unlabeled break to the break target or to an equivalent break.
shortBreak.use();
accumulator.add(new js.Break(null));
accumulator.add(new js.Break(null));
} else {
usedLabels.add(node.target);
accumulator.add(new js.Break(node.target.name));
@ -547,7 +555,8 @@ class CodeGenerator extends tree_ir.StatementVisitor
registry.registerCompileTimeConstant(new NullConstantValue());
fallthrough.use();
} else {
accumulator.add(new js.Return(visitExpression(node.value)));
accumulator.add(new js.Return(visitExpression(node.value))
.withSourceInformation(node.sourceInformation));
}
}
@ -596,7 +605,8 @@ class CodeGenerator extends tree_ir.StatementVisitor
}
js.Expression instance = new js.New(
glue.constructorAccess(classElement),
visitExpressionList(node.arguments));
visitExpressionList(node.arguments))
.withSourceInformation(node.sourceInformation);
List<tree_ir.Expression> typeInformation = node.typeInformation;
assert(typeInformation.isEmpty ||
@ -606,7 +616,8 @@ class CodeGenerator extends tree_ir.StatementVisitor
js.Expression typeArguments = new js.ArrayInitializer(
visitExpressionList(typeInformation));
return buildStaticHelperInvocation(helper,
<js.Expression>[instance, typeArguments]);
<js.Expression>[instance, typeArguments],
sourceInformation: node.sourceInformation);
} else {
return instance;
}
@ -704,19 +715,25 @@ class CodeGenerator extends tree_ir.StatementVisitor
visitExpression(node.value)]);
}
js.Expression buildStaticHelperInvocation(FunctionElement helper,
List<js.Expression> arguments) {
js.Expression buildStaticHelperInvocation(
FunctionElement helper,
List<js.Expression> arguments,
{SourceInformation sourceInformation}) {
registry.registerStaticUse(helper);
return buildStaticInvoke(helper, arguments);
return buildStaticInvoke(
helper, arguments, sourceInformation: sourceInformation);
}
@override
js.Expression visitReifyRuntimeType(tree_ir.ReifyRuntimeType node) {
FunctionElement createType = glue.getCreateRuntimeType();
FunctionElement typeToString = glue.getRuntimeTypeToString();
return buildStaticHelperInvocation(createType,
[buildStaticHelperInvocation(typeToString,
[visitExpression(node.value)])]);
js.Expression typeToString = buildStaticHelperInvocation(
glue.getRuntimeTypeToString(),
[visitExpression(node.value)],
sourceInformation: node.sourceInformation);
return buildStaticHelperInvocation(
glue.getCreateRuntimeType(),
[typeToString],
sourceInformation: node.sourceInformation);
}
@override
@ -727,11 +744,13 @@ class CodeGenerator extends tree_ir.StatementVisitor
js.Expression typeName = glue.getRuntimeTypeName(context);
return buildStaticHelperInvocation(
glue.getRuntimeTypeArgument(),
[visitExpression(node.target), typeName, index]);
[visitExpression(node.target), typeName, index],
sourceInformation: node.sourceInformation);
} else {
return buildStaticHelperInvocation(
glue.getTypeArgumentByIndex(),
[visitExpression(node.target), index]);
[visitExpression(node.target), index],
sourceInformation: node.sourceInformation);
}
}

View File

@ -2191,8 +2191,10 @@ class SsaBuilder extends ast.Visitor
constructorArguments,
instantiatedTypes);
if (function != null) {
// TODO(johnniwinther): Provide source information for creation
// through synthetic constructors.
newObject.sourceInformation =
sourceInformationBuilder.buildGeneric(function);
sourceInformationBuilder.buildCreate(function);
}
add(newObject);
} else {
@ -3147,7 +3149,7 @@ class SsaBuilder extends ast.Visitor
TypeMask type =
new TypeMask.nonNullExact(compiler.functionClass, compiler.world);
push(new HForeignNew(closureClassElement, type, capturedVariables)
..sourceInformation = sourceInformationBuilder.buildGeneric(node));
..sourceInformation = sourceInformationBuilder.buildCreate(node));
Element methodElement = nestedClosureData.closureElement;
registry.registerInstantiatedClosure(methodElement);

View File

@ -6,6 +6,7 @@ library tree_ir.optimization.statement_rewriter;
import 'optimization.dart' show Pass;
import '../tree_ir_nodes.dart';
import '../../io/source_information.dart';
/**
* Translates to direct-style.
@ -924,7 +925,11 @@ class StatementRewriter extends Transformer implements Pass {
if (s is Return && t is Return) {
CombinedExpressions values = combineExpressions(s.value, t.value);
if (values != null) {
return new Return(values.combined);
// TODO(johnniwinther): Handle multiple source informations.
SourceInformation sourceInformation = s.sourceInformation != null
? s.sourceInformation : t.sourceInformation;
return new Return(values.combined,
sourceInformation: sourceInformation);
}
}
if (s is ExpressionStatement && t is ExpressionStatement) {

View File

@ -274,7 +274,8 @@ class Builder implements cps_ir.Visitor<Node> {
return new CreateInstance(
node.classElement,
translateArguments(node.arguments),
translateArguments(node.typeInformation));
translateArguments(node.typeInformation),
node.sourceInformation);
}
Expression visitGetField(cps_ir.GetField node) {
@ -355,10 +356,12 @@ class Builder implements cps_ir.Visitor<Node> {
}
Statement visitInvokeMethod(cps_ir.InvokeMethod node) {
InvokeMethod invoke = new InvokeMethod(getVariableUse(node.receiver),
node.selector,
node.mask,
translateArguments(node.arguments));
InvokeMethod invoke = new InvokeMethod(
getVariableUse(node.receiver),
node.selector,
node.mask,
translateArguments(node.arguments),
node.sourceInformation);
invoke.receiverIsNotNull = node.receiverIsNotNull;
return continueWithExpression(node.continuation, invoke);
}
@ -367,7 +370,7 @@ class Builder implements cps_ir.Visitor<Node> {
Expression receiver = getVariableUse(node.receiver);
List<Expression> arguments = translateArguments(node.arguments);
Expression invoke = new InvokeMethodDirectly(receiver, node.target,
node.selector, arguments);
node.selector, arguments, node.sourceInformation);
return continueWithExpression(node.continuation, invoke);
}
@ -439,7 +442,8 @@ class Builder implements cps_ir.Visitor<Node> {
node.type,
node.target,
node.selector,
arguments);
arguments,
node.sourceInformation);
return continueWithExpression(node.continuation, invoke);
}
@ -452,7 +456,8 @@ class Builder implements cps_ir.Visitor<Node> {
cps_ir.Continuation cont = node.continuation.definition;
if (cont == returnContinuation) {
assert(node.arguments.length == 1);
return new Return(getVariableUse(node.arguments.single));
return new Return(getVariableUse(node.arguments.single),
sourceInformation: node.sourceInformation);
} else {
List<Expression> arguments = translateArguments(node.arguments);
return buildPhiAssignments(cont.parameters, arguments,
@ -500,7 +505,7 @@ class Builder implements cps_ir.Visitor<Node> {
}
Expression visitConstant(cps_ir.Constant node) {
return new Constant(node.value);
return new Constant(node.value, sourceInformation: node.sourceInformation);
}
Expression visitLiteralList(cps_ir.LiteralList node) {
@ -552,11 +557,15 @@ class Builder implements cps_ir.Visitor<Node> {
}
Expression visitReifyRuntimeType(cps_ir.ReifyRuntimeType node) {
return new ReifyRuntimeType(getVariableUse(node.value));
return new ReifyRuntimeType(
getVariableUse(node.value), node.sourceInformation);
}
Expression visitReadTypeVariable(cps_ir.ReadTypeVariable node) {
return new ReadTypeVariable(node.variable, getVariableUse(node.target));
return new ReadTypeVariable(
node.variable,
getVariableUse(node.target),
node.sourceInformation);
}
@override

View File

@ -201,11 +201,16 @@ class InvokeMethod extends Expression implements Invoke {
final Selector selector;
final TypeMask mask;
final List<Expression> arguments;
final SourceInformation sourceInformation;
/// If true, it is known that the receiver cannot be `null`.
bool receiverIsNotNull = false;
InvokeMethod(this.receiver, this.selector, this.mask, this.arguments) {
InvokeMethod(this.receiver,
this.selector,
this.mask,
this.arguments,
this.sourceInformation) {
assert(receiver != null);
}
@ -224,9 +229,10 @@ class InvokeMethodDirectly extends Expression implements Invoke {
final Element target;
final Selector selector;
final List<Expression> arguments;
final SourceInformation sourceInformation;
InvokeMethodDirectly(this.receiver, this.target, this.selector,
this.arguments);
this.arguments, this.sourceInformation);
accept(ExpressionVisitor visitor) => visitor.visitInvokeMethodDirectly(this);
accept1(ExpressionVisitor1 visitor, arg) {
@ -242,12 +248,13 @@ class InvokeConstructor extends Expression implements Invoke {
final FunctionElement target;
final List<Expression> arguments;
final Selector selector;
final SourceInformation sourceInformation;
/// TODO(karlklose): get rid of this field. Instead use the constant's
/// expression to find the constructor to be called in dart2dart.
final values.ConstantValue constant;
InvokeConstructor(this.type, this.target, this.selector, this.arguments,
[this.constant]);
this.sourceInformation, [this.constant]);
ClassElement get targetClass => target.enclosingElement;
@ -265,14 +272,18 @@ class InvokeConstructor extends Expression implements Invoke {
*/
class Constant extends Expression {
final values.ConstantValue value;
final SourceInformation sourceInformation;
Constant(this.value);
Constant(this.value, {this.sourceInformation});
Constant.bool(values.BoolConstantValue constantValue)
: value = constantValue;
: value = constantValue,
sourceInformation = null;
accept(ExpressionVisitor visitor) => visitor.visitConstant(this);
accept1(ExpressionVisitor1 visitor, arg) => visitor.visitConstant(this, arg);
String toString() => 'Constant(value=${value.toStructuredString()})';
}
class This extends Expression {
@ -364,6 +375,9 @@ class Conditional extends Expression {
accept1(ExpressionVisitor1 visitor, arg) {
return visitor.visitConditional(this, arg);
}
String toString() => 'Conditional(condition=$condition,thenExpression='
'$thenExpression,elseExpression=$elseExpression)';
}
/// An && or || expression. The operator is internally represented as a boolean
@ -383,6 +397,8 @@ class LogicalOperator extends Expression {
accept1(ExpressionVisitor1 visitor, arg) {
return visitor.visitLogicalOperator(this, arg);
}
String toString() => 'LogicalOperator(left=$left,right=$right,isAnd=$isAnd)';
}
/// Logical negation.
@ -541,11 +557,12 @@ class Return extends Statement {
/// Even in constructors this holds true. Take special care when translating
/// back to dart, where `return null;` in a constructor is an error.
Expression value;
SourceInformation sourceInformation;
Statement get next => null;
void set next(Statement s) => throw 'UNREACHABLE';
Return(this.value);
Return(this.value, {this.sourceInformation});
accept(StatementVisitor visitor) => visitor.visitReturn(this);
accept1(StatementVisitor1 visitor, arg) => visitor.visitReturn(this, arg);
@ -664,8 +681,10 @@ class CreateInstance extends Expression {
ClassElement classElement;
List<Expression> arguments;
List<Expression> typeInformation;
SourceInformation sourceInformation;
CreateInstance(this.classElement, this.arguments, this.typeInformation);
CreateInstance(this.classElement, this.arguments,
this.typeInformation, this.sourceInformation);
accept(ExpressionVisitor visitor) => visitor.visitCreateInstance(this);
accept1(ExpressionVisitor1 visitor, arg) {
@ -749,8 +768,9 @@ class SetIndex extends Expression {
class ReifyRuntimeType extends Expression {
Expression value;
SourceInformation sourceInformation;
ReifyRuntimeType(this.value);
ReifyRuntimeType(this.value, this.sourceInformation);
accept(ExpressionVisitor visitor) {
return visitor.visitReifyRuntimeType(this);
@ -764,8 +784,9 @@ class ReifyRuntimeType extends Expression {
class ReadTypeVariable extends Expression {
final TypeVariableType variable;
Expression target;
final SourceInformation sourceInformation;
ReadTypeVariable(this.variable, this.target);
ReadTypeVariable(this.variable, this.target, this.sourceInformation);
accept(ExpressionVisitor visitor) {
return visitor.visitReadTypeVariable(this);

View File

@ -36,6 +36,7 @@ invokes(parameter) {
parameter();
localVariable();
localFunction();
(parameter)();
parameter.dynamicInvoke();
new C(parameter).instanceInvokes();

View File

@ -2,6 +2,7 @@
// 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.
import 'dart:async';
import 'package:async_helper/async_helper.dart';
import 'package:expect/expect.dart';
import 'sourcemap_helper.dart';
@ -10,42 +11,134 @@ import 'package:compiler/src/filenames.dart';
main(List<String> arguments) {
bool showAll = false;
bool measure = false;
Uri outputUri;
if (arguments.isNotEmpty) {
outputUri = Uri.base.resolve(nativeToUriPath(arguments.last));
showAll = arguments.contains('-a');
}
asyncTest(() async {
String filename =
'tests/compiler/dart2js/sourcemaps/invokes_test_file.dart';
SourceMapProcessor processor = new SourceMapProcessor(filename);
List<SourceMapInfo> infoList = await processor.process(
['--use-new-source-info', '--csp', '--disable-inlining']);
List<SourceMapInfo> userInfoList = <SourceMapInfo>[];
List<SourceMapInfo> failureList = <SourceMapInfo>[];
for (SourceMapInfo info in infoList) {
if (info.element.library.isPlatformLibrary) continue;
userInfoList.add(info);
Iterable<CodePoint> missingCodePoints =
info.codePoints.where((c) => c.isMissing);
if (!missingCodePoints.isEmpty) {
print('Missing code points ${missingCodePoints} for '
'${info.element} in $filename');
failureList.add(info);
Set<String> configurations = new Set<String>();
for (String argument in arguments) {
if (argument.startsWith('-')) {
if (argument == '-a') {
/// Generate visualization for all user methods.
showAll = true;
} else if (argument == '-m') {
/// Measure instead of reporting the number of missing code points.
measure = true;
} else if (argument.startsWith('--out=')) {
/// Generate visualization for the first configuration.
outputUri = Uri.base.resolve(
nativeToUriPath(argument.substring('--out='.length)));
} else if (argument.startsWith('-o')) {
/// Generate visualization for the first configuration.
outputUri = Uri.base.resolve(
nativeToUriPath(argument.substring('-o'.length)));
} else {
print("Unknown option '$argument'.");
return;
}
} else {
if (TEST_CONFIGURATIONS.containsKey(argument)) {
configurations.add(argument);
} else {
print("Unknown configuration '$argument'. "
"Must be one of '${TEST_CONFIGURATIONS.keys.join("', '")}'");
return;
}
}
if (failureList.isNotEmpty) {
if (outputUri == null) {
Expect.fail(
"Missing code points found. "
"Run the test with a URI option, `source_mapping_test <uri>`, to "
"create a html visualization of the missing code points.");
} else {
createTraceSourceMapHtml(outputUri, processor,
showAll ? userInfoList : failureList);
}
if (configurations.isEmpty) {
configurations.addAll(TEST_CONFIGURATIONS.keys);
}
String outputConfig = configurations.first;
asyncTest(() async {
List<Measurement> measurements = <Measurement>[];
for (String config in configurations) {
List<String> options = TEST_CONFIGURATIONS[config];
Measurement measurement = await runTests(
config,
options,
showAll: showAll,
measure: measure,
outputUri: outputConfig == config ? outputUri : null);
if (measurement != null) {
measurements.add(measurement);
}
} else if (outputUri != null) {
createTraceSourceMapHtml(outputUri, processor, userInfoList);
}
for (Measurement measurement in measurements) {
print(measurement);
}
});
}
const Map<String, List<String>> TEST_CONFIGURATIONS = const {
'old': const [],
'ssa': const ['--use-new-source-info', ],
'cps': const ['--use-new-source-info', '--use-cps-ir'],
};
Future<Measurement> runTests(
String config,
List<String> options,
{bool showAll: false,
Uri outputUri,
bool measure: false}) async {
if (config == 'old' && !measure) return null;
String filename =
'tests/compiler/dart2js/sourcemaps/invokes_test_file.dart';
SourceMapProcessor processor = new SourceMapProcessor(filename);
List<SourceMapInfo> infoList = await processor.process(
['--csp', '--disable-inlining']
..addAll(options),
verbose: !measure);
List<SourceMapInfo> userInfoList = <SourceMapInfo>[];
List<SourceMapInfo> failureList = <SourceMapInfo>[];
Measurement measurement = new Measurement(config);
for (SourceMapInfo info in infoList) {
if (info.element.library.isPlatformLibrary) continue;
userInfoList.add(info);
Iterable<CodePoint> missingCodePoints =
info.codePoints.where((c) => c.isMissing);
measurement.missing += missingCodePoints.length;
measurement.count += info.codePoints.length;
if (!measure) {
if (!missingCodePoints.isEmpty) {
print("Missing code points for ${info.element} in '$filename':");
for (CodePoint codePoint in missingCodePoints) {
print(" $codePoint");
}
failureList.add(info);
}
}
}
if (failureList.isNotEmpty) {
if (outputUri == null) {
if (!measure) {
Expect.fail(
"Missing code points found. "
"Run the test with a URI option, "
"`source_mapping_test --out=<uri> $config`, to "
"create a html visualization of the missing code points.");
}
} else {
createTraceSourceMapHtml(outputUri, processor,
showAll ? userInfoList : failureList);
}
} else if (outputUri != null) {
createTraceSourceMapHtml(outputUri, processor, userInfoList);
}
return measurement;
}
class Measurement {
final String config;
int missing = 0;
int count = 0;
Measurement(this.config);
String toString() {
double percentage = 100 * missing / count;
return "Config '${config}': $missing of $count ($percentage%) missing";
}
}

View File

@ -7,7 +7,8 @@ library sourcemap.helper;
import 'dart:async';
import 'package:compiler/src/apiimpl.dart' as api;
import 'package:compiler/src/dart2jslib.dart' show NullSink;
import "package:compiler/src/elements/elements.dart";
import 'package:compiler/src/elements/elements.dart';
import 'package:compiler/src/helpers/helpers.dart';
import 'package:compiler/src/filenames.dart';
import 'package:compiler/src/io/source_file.dart';
import 'package:compiler/src/io/source_information.dart';
@ -106,20 +107,23 @@ class SourceMapProcessor {
}
/// Computes the [SourceMapInfo] for the compiled elements.
Future<List<SourceMapInfo>> process(List<String> options) async {
Future<List<SourceMapInfo>> process(
List<String> options,
{bool verbose: true}) async {
OutputProvider outputProvider = outputToFile
? new OutputProvider()
: new CloningOutputProvider(targetUri, sourceMapFileUri);
if (options.contains('--use-new-source-info')) {
print('Using the new source information system.');
if (verbose) print('Using the new source information system.');
useNewSourceInfo = true;
}
api.Compiler compiler = await compilerFor({},
outputProvider: outputProvider,
// TODO(johnniwinther): Use [verbose] to avoid showing diagnostics.
options: ['--out=$targetUri', '--source-map=$sourceMapFileUri']
..addAll(options));
if (options.contains('--disable-inlining')) {
print('Inlining disabled');
if (verbose) print('Inlining disabled');
compiler.disableInlining = true;
}