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 07e7793f7a583400a5f9a78dd01a7646032b21b0..f866a0ff989f46e37a7c7f899aa2f7f93147f9cc 100644 |
--- a/pkg/compiler/lib/src/ssa/builder.dart |
+++ b/pkg/compiler/lib/src/ssa/builder.dart |
@@ -10,7 +10,7 @@ class SsaFunctionCompiler implements FunctionCompiler { |
SsaOptimizerTask optimizer; |
SsaFunctionCompiler(JavaScriptBackend backend, |
- SourceInformationFactory sourceInformationFactory) |
+ SourceInformationStrategy sourceInformationFactory) |
: generator = new SsaCodeGeneratorTask(backend, sourceInformationFactory), |
builder = new SsaBuilderTask(backend, sourceInformationFactory), |
optimizer = new SsaOptimizerTask(backend); |
@@ -97,7 +97,7 @@ class SyntheticLocal extends Local { |
class SsaBuilderTask extends CompilerTask { |
final CodeEmitterTask emitter; |
final JavaScriptBackend backend; |
- final SourceInformationFactory sourceInformationFactory; |
+ final SourceInformationStrategy sourceInformationFactory; |
String get name => 'SSA builder'; |
@@ -480,7 +480,8 @@ class LocalsHandler { |
* boxed or stored in a closure then the method generates code to retrieve |
* the value. |
*/ |
- HInstruction readLocal(Local local) { |
+ HInstruction readLocal(Local local, |
+ {SourceInformation sourceInformation}) { |
if (isAccessedDirectly(local)) { |
if (directLocals[local] == null) { |
if (local is TypeVariableElement) { |
@@ -500,7 +501,7 @@ class LocalsHandler { |
: builder.getTypeOfCapturedVariable(redirect); |
HInstruction fieldGet = new HFieldGet(redirect, receiver, type); |
builder.add(fieldGet); |
- return fieldGet; |
+ return fieldGet..sourceInformation = sourceInformation; |
} else if (isBoxed(local)) { |
BoxFieldElement redirect = redirectionMapping[local]; |
// In the function that declares the captured variable the box is |
@@ -512,14 +513,14 @@ class LocalsHandler { |
HInstruction lookup = new HFieldGet( |
redirect, box, builder.getTypeOfCapturedVariable(redirect)); |
builder.add(lookup); |
- return lookup; |
+ return lookup..sourceInformation = sourceInformation; |
} else { |
assert(isUsedInTryOrGenerator(local)); |
HLocalValue localValue = getLocal(local); |
HInstruction instruction = new HLocalGet( |
local, localValue, builder.backend.dynamicType); |
builder.add(instruction); |
- return instruction; |
+ return instruction..sourceInformation = sourceInformation; |
} |
} |
@@ -531,7 +532,8 @@ class LocalsHandler { |
return res; |
} |
- HLocalValue getLocal(Local local) { |
+ HLocalValue getLocal(Local local, |
+ {SourceInformation sourceInformation}) { |
// If the element is a parameter, we already have a |
// HParameterValue for it. We cannot create another one because |
// it could then have another name than the real parameter. And |
@@ -541,7 +543,8 @@ class LocalsHandler { |
return builder.activationVariables.putIfAbsent(local, () { |
JavaScriptBackend backend = builder.backend; |
- HLocalValue localValue = new HLocalValue(local, backend.nonNullType); |
+ HLocalValue localValue = new HLocalValue(local, backend.nonNullType) |
+ ..sourceInformation = sourceInformation; |
builder.graph.entry.addAtExit(localValue); |
return localValue; |
}); |
@@ -557,7 +560,8 @@ class LocalsHandler { |
* Sets the [element] to [value]. If the element is boxed or stored in a |
* closure then the method generates code to set the value. |
*/ |
- void updateLocal(Local local, HInstruction value) { |
+ void updateLocal(Local local, HInstruction value, |
+ {SourceInformation sourceInformation}) { |
assert(!isStoredInClosureField(local)); |
if (isAccessedDirectly(local)) { |
directLocals[local] = value; |
@@ -568,11 +572,13 @@ class LocalsHandler { |
// Inside the closure the box is stored in a closure-field and cannot |
// be accessed directly. |
HInstruction box = readLocal(redirect.box); |
- builder.add(new HFieldSet(redirect, box, value)); |
+ builder.add(new HFieldSet(redirect, box, value) |
+ ..sourceInformation = sourceInformation); |
} else { |
assert(isUsedInTryOrGenerator(local)); |
HLocalValue localValue = getLocal(local); |
- builder.add(new HLocalSet(local, localValue, value)); |
+ builder.add(new HLocalSet(local, localValue, value) |
+ ..sourceInformation = sourceInformation); |
} |
} |
@@ -1119,7 +1125,7 @@ class SsaBuilder extends ast.Visitor |
SsaBuilder(JavaScriptBackend backend, |
CodegenWorkItem work, |
this.nativeEmitter, |
- SourceInformationFactory sourceInformationFactory) |
+ SourceInformationStrategy sourceInformationFactory) |
: this.compiler = backend.compiler, |
this.backend = backend, |
this.constantSystem = backend.constantSystem, |
@@ -1129,7 +1135,8 @@ class SsaBuilder extends ast.Visitor |
localsHandler = new LocalsHandler(this, work.element, null); |
sourceElementStack.add(work.element); |
sourceInformationBuilder = |
- sourceInformationFactory.forContext(work.element.implementation); |
+ sourceInformationFactory.createBuilderForContext( |
+ work.element.implementation); |
} |
@override |
@@ -1635,17 +1642,19 @@ class SsaBuilder extends ast.Visitor |
if (!backend.operatorEqHandlesNullArgument(functionElement)) { |
handleIf( |
function, |
- () { |
+ visitCondition: () { |
HParameterValue parameter = parameters.values.first; |
push(new HIdentity( |
parameter, graph.addConstantNull(compiler), null, |
backend.boolType)); |
}, |
- () { |
+ visitThen: () { |
+ // TODO(johnniwinther): Add source information. |
closeAndGotoExit(new HReturn( |
- graph.addConstantBool(false, compiler))); |
+ graph.addConstantBool(false, compiler), |
+ null)); |
}, |
- null); |
+ visitElse: null); |
} |
} |
function.body.accept(this); |
@@ -1669,14 +1678,16 @@ class SsaBuilder extends ast.Visitor |
HGraph buildLazyInitializer(VariableElement variable) { |
inLazyInitializerExpression = true; |
- ast.Node node = variable.node; |
+ ast.VariableDefinitions node = variable.node; |
openFunction(variable, node); |
assert(invariant(variable, variable.initializer != null, |
message: "Non-constant variable $variable has no initializer.")); |
visit(variable.initializer); |
HInstruction value = pop(); |
value = potentiallyCheckOrTrustType(value, variable.type); |
- closeAndGotoExit(new HReturn(value)); |
+ ast.SendSet sendSet = node.definitions.nodes.head; |
+ closeAndGotoExit(new HReturn(value, |
+ sourceInformationBuilder.buildReturn(sendSet.assignmentOperator))); |
return closeFunction(); |
} |
@@ -2179,6 +2190,10 @@ class SsaBuilder extends ast.Visitor |
ssaType, |
constructorArguments, |
instantiatedTypes); |
+ if (function != null) { |
+ newObject.sourceInformation = |
+ sourceInformationBuilder.buildGeneric(function); |
+ } |
add(newObject); |
} else { |
// Bulk assign to the initialized fields. |
@@ -2332,7 +2347,8 @@ class SsaBuilder extends ast.Visitor |
} |
} |
if (inliningStack.isEmpty) { |
- closeAndGotoExit(new HReturn(newObject)); |
+ closeAndGotoExit(new HReturn(newObject, |
+ sourceInformationBuilder.buildImplicitReturn(functionElement))); |
return closeFunction(); |
} else { |
localsHandler.updateLocal(returnLocal, newObject); |
@@ -2634,7 +2650,8 @@ class SsaBuilder extends ast.Visitor |
if (throwExpression != null && inliningStack.isEmpty) { |
visitThrowExpression(throwExpression.expression); |
handleInTryStatement(); |
- closeAndGotoExit(new HThrow(pop())); |
+ closeAndGotoExit( |
+ new HThrow(pop(), sourceInformationBuilder.buildThrow(node))); |
} else { |
visit(node.expression); |
pop(); |
@@ -3129,7 +3146,8 @@ class SsaBuilder extends ast.Visitor |
TypeMask type = |
new TypeMask.nonNullExact(compiler.functionClass, compiler.world); |
- push(new HForeignNew(closureClassElement, type, capturedVariables)); |
+ push(new HForeignNew(closureClassElement, type, capturedVariables) |
+ ..sourceInformation = sourceInformationBuilder.buildGeneric(node)); |
Element methodElement = nestedClosureData.closureElement; |
registry.registerInstantiatedClosure(methodElement); |
@@ -3159,16 +3177,23 @@ class SsaBuilder extends ast.Visitor |
visitIf(ast.If node) { |
assert(isReachable); |
- handleIf(node, |
- () => visit(node.condition), |
- () => visit(node.thenPart), |
- node.elsePart != null ? () => visit(node.elsePart) : null); |
+ handleIf( |
+ node, |
+ visitCondition: () => visit(node.condition), |
+ visitThen: () => visit(node.thenPart), |
+ visitElse: node.elsePart != null ? () => visit(node.elsePart) : null, |
+ sourceInformation: sourceInformationBuilder.buildIf(node)); |
} |
void handleIf(ast.Node diagnosticNode, |
- void visitCondition(), void visitThen(), void visitElse()) { |
+ {void visitCondition(), |
+ void visitThen(), |
+ void visitElse(), |
+ SourceInformation sourceInformation}) { |
SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, diagnosticNode); |
- branchBuilder.handleIf(visitCondition, visitThen, visitElse); |
+ branchBuilder.handleIf( |
+ visitCondition, visitThen, visitElse, |
+ sourceInformation: sourceInformation); |
} |
@override |
@@ -3199,8 +3224,10 @@ class SsaBuilder extends ast.Visitor |
void visitNot(ast.Send node, ast.Node expression, _) { |
assert(node.argumentsNode is ast.Prefix); |
visit(expression); |
- HNot not = new HNot(popBoolified(), backend.boolType); |
- pushWithPosition(not, node); |
+ SourceInformation sourceInformation = |
+ sourceInformationBuilder.buildGeneric(node); |
+ push(new HNot(popBoolified(), backend.boolType) |
+ ..sourceInformation = sourceInformation); |
} |
@override |
@@ -3225,7 +3252,8 @@ class SsaBuilder extends ast.Visitor |
node, |
elements.getSelector(node), |
elements.getTypeMask(node), |
- [operand]); |
+ [operand], |
+ sourceInformation: sourceInformationBuilder.buildGeneric(node)); |
} |
@override |
@@ -3259,7 +3287,8 @@ class SsaBuilder extends ast.Visitor |
elements.getSelector(node), |
elements.getTypeMask(node), |
node, |
- location: node.selector); |
+ sourceInformation: |
+ sourceInformationBuilder.buildGeneric(node.selector)); |
} |
/// TODO(johnniwinther): Merge [visitBinarySend] with [handleBinary] and |
@@ -3269,8 +3298,9 @@ class SsaBuilder extends ast.Visitor |
Selector selector, |
TypeMask mask, |
ast.Send send, |
- {ast.Node location}) { |
- pushInvokeDynamic(send, selector, mask, [left, right], location: location); |
+ {SourceInformation sourceInformation}) { |
+ pushInvokeDynamic(send, selector, mask, [left, right], |
+ sourceInformation: sourceInformation); |
} |
HInstruction generateInstanceSendReceiver(ast.Send send) { |
@@ -3299,7 +3329,8 @@ class SsaBuilder extends ast.Visitor |
HInstruction receiver) { |
assert(Elements.isInstanceSend(send, elements)); |
assert(selector.isGetter); |
- pushInvokeDynamic(send, selector, mask, [receiver]); |
+ pushInvokeDynamic(send, selector, mask, [receiver], |
+ sourceInformation: sourceInformationBuilder.buildGet(send)); |
} |
/// Inserts a call to checkDeferredIsLoaded for [prefixElement]. |
@@ -3326,15 +3357,20 @@ class SsaBuilder extends ast.Visitor |
} |
void handleInvalidStaticGet(ast.Send node, Element element) { |
+ SourceInformation sourceInformation = |
+ sourceInformationBuilder.buildGet(node); |
generateThrowNoSuchMethod( |
node, |
noSuchMethodTargetSymbolString(element, 'get'), |
- argumentNodes: const Link<ast.Node>()); |
+ argumentNodes: const Link<ast.Node>(), |
+ sourceInformation: sourceInformation); |
} |
/// Generate read access of an unresolved static or top level entity. |
void generateStaticUnresolvedGet(ast.Send node, Element element) { |
if (element is ErroneousElement) { |
+ SourceInformation sourceInformation = |
+ sourceInformationBuilder.buildGet(node); |
// An erroneous element indicates an unresolved static getter. |
handleInvalidStaticGet(node, element); |
} else { |
@@ -3350,7 +3386,8 @@ class SsaBuilder extends ast.Visitor |
void generateStaticConstGet( |
ast.Send node, |
FieldElement field, |
- ConstantExpression constant) { |
+ ConstantExpression constant, |
+ SourceInformation sourceInformation) { |
ConstantValue value = backend.constants.getConstantValue(constant); |
HConstant instruction; |
// Constants that are referred via a deferred prefix should be referred |
@@ -3358,9 +3395,11 @@ class SsaBuilder extends ast.Visitor |
PrefixElement prefix = compiler.deferredLoadTask |
.deferredPrefixElement(node, elements); |
if (prefix != null) { |
- instruction = graph.addDeferredConstant(value, prefix, compiler); |
+ instruction = |
+ graph.addDeferredConstant(value, prefix, sourceInformation, compiler); |
} else { |
- instruction = graph.addConstant(value, compiler); |
+ instruction = graph.addConstant( |
+ value, compiler, sourceInformation: sourceInformation); |
} |
stack.add(instruction); |
// The inferrer may have found a better type than the constant |
@@ -3382,34 +3421,41 @@ class SsaBuilder extends ast.Visitor |
ConstantExpression constant = |
backend.constants.getConstantForVariable(field); |
+ SourceInformation sourceInformation = |
+ sourceInformationBuilder.buildGet(node); |
if (constant != null) { |
if (!field.isAssignable) { |
// A static final or const. Get its constant value and inline it if |
// the value can be compiled eagerly. |
- generateStaticConstGet(node, field, constant); |
+ generateStaticConstGet(node, field, constant, sourceInformation); |
} else { |
// TODO(5346): Try to avoid the need for calling [declaration] before |
// creating an [HStatic]. |
HInstruction instruction = new HStatic( |
field.declaration, |
- TypeMaskFactory.inferredTypeForElement(field, compiler)); |
+ TypeMaskFactory.inferredTypeForElement(field, compiler)) |
+ ..sourceInformation = sourceInformation; |
push(instruction); |
} |
} else { |
HInstruction instruction = new HLazyStatic( |
field, |
- TypeMaskFactory.inferredTypeForElement(field, compiler)); |
+ TypeMaskFactory.inferredTypeForElement(field, compiler)) |
+ ..sourceInformation = sourceInformation; |
push(instruction); |
} |
} |
/// Generate a getter invocation of the static or top level [getter]. |
void generateStaticGetterGet(ast.Send node, MethodElement getter) { |
+ SourceInformation sourceInformation = |
+ sourceInformationBuilder.buildGet(node); |
if (getter.isDeferredLoaderGetter) { |
- generateDeferredLoaderGet(node, getter); |
+ generateDeferredLoaderGet(node, getter, sourceInformation); |
} else { |
generateIsDeferredLoadedCheckOfSend(node); |
- pushInvokeStatic(node, getter, <HInstruction>[]); |
+ pushInvokeStatic(node, getter, <HInstruction>[], |
+ sourceInformation: sourceInformation); |
} |
} |
@@ -3425,12 +3471,20 @@ class SsaBuilder extends ast.Visitor |
generateIsDeferredLoadedCheckOfSend(node); |
// TODO(5346): Try to avoid the need for calling [declaration] before |
// creating an [HStatic]. |
- push(new HStatic(function.declaration, backend.nonNullType)); |
+ SourceInformation sourceInformation = |
+ sourceInformationBuilder.buildGet(node); |
+ push(new HStatic(function.declaration, backend.nonNullType) |
+ ..sourceInformation = sourceInformation); |
} |
/// Read a local variable, function or parameter. |
- void handleLocalGet(LocalElement local) { |
- stack.add(localsHandler.readLocal(local)); |
+ void buildLocalGet(LocalElement local, SourceInformation sourceInformation) { |
+ stack.add(localsHandler.readLocal( |
+ local, sourceInformation: sourceInformation)); |
+ } |
+ |
+ void handleLocalGet(ast.Send node, LocalElement local) { |
+ buildLocalGet(local, sourceInformationBuilder.buildGet(node)); |
} |
@override |
@@ -3479,17 +3533,17 @@ class SsaBuilder extends ast.Visitor |
@override |
void visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) { |
- handleLocalGet(variable); |
+ handleLocalGet(node, variable); |
} |
@override |
void visitParameterGet(ast.Send node, ParameterElement parameter, _) { |
- handleLocalGet(parameter); |
+ handleLocalGet(node, parameter); |
} |
@override |
void visitLocalFunctionGet(ast.Send node, LocalFunctionElement function, _) { |
- handleLocalGet(function); |
+ handleLocalGet(node, function); |
} |
@override |
@@ -3567,7 +3621,8 @@ class SsaBuilder extends ast.Visitor |
location = send; |
} |
assert(selector.isSetter); |
- pushInvokeDynamic(location, selector, mask, [receiver, value]); |
+ pushInvokeDynamic(location, selector, mask, [receiver, value], |
+ sourceInformation: sourceInformationBuilder.buildAssignment(location)); |
pop(); |
stack.add(value); |
} |
@@ -3617,7 +3672,9 @@ class SsaBuilder extends ast.Visitor |
stack.add(checkedOrTrusted); |
} |
- localsHandler.updateLocal(local, checkedOrTrusted); |
+ localsHandler.updateLocal(local, checkedOrTrusted, |
+ sourceInformation: |
+ sourceInformationBuilder.buildAssignment(location)); |
} |
} |
@@ -3827,12 +3884,15 @@ class SsaBuilder extends ast.Visitor |
void _generateDynamicSend(ast.Send node, HInstruction receiver) { |
Selector selector = elements.getSelector(node); |
TypeMask mask = elements.getTypeMask(node); |
+ SourceInformation sourceInformation = |
+ sourceInformationBuilder.buildCall(node, node.selector); |
List<HInstruction> inputs = <HInstruction>[]; |
inputs.add(receiver); |
addDynamicSendArgumentsToList(node, inputs); |
- pushInvokeDynamic(node, selector, mask, inputs); |
+ pushInvokeDynamic(node, selector, mask, inputs, |
+ sourceInformation: sourceInformation); |
if (selector.isSetter || selector.isIndexSet) { |
pop(); |
stack.add(inputs.last); |
@@ -3884,7 +3944,10 @@ class SsaBuilder extends ast.Visitor |
ast.NodeList arguments, |
Selector selector, |
_) { |
- generateCallInvoke(node, visitAndPop(expression)); |
+ generateCallInvoke( |
+ node, |
+ visitAndPop(expression), |
+ sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
} |
@override |
@@ -3893,7 +3956,10 @@ class SsaBuilder extends ast.Visitor |
ast.NodeList arguments, |
CallStructure callStructure, |
_) { |
- generateCallInvoke(node, localsHandler.readThis()); |
+ generateCallInvoke( |
+ node, |
+ localsHandler.readThis(), |
+ sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
} |
@override |
@@ -3903,7 +3969,10 @@ class SsaBuilder extends ast.Visitor |
ast.NodeList arguments, |
CallStructure callStructure, |
_) { |
- generateCallInvoke(node, localsHandler.readLocal(parameter)); |
+ generateCallInvoke( |
+ node, |
+ localsHandler.readLocal(parameter), |
+ sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
} |
@override |
@@ -3913,7 +3982,10 @@ class SsaBuilder extends ast.Visitor |
ast.NodeList arguments, |
CallStructure callStructure, |
_) { |
- generateCallInvoke(node, localsHandler.readLocal(variable)); |
+ generateCallInvoke( |
+ node, |
+ localsHandler.readLocal(variable), |
+ sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
} |
@override |
@@ -3923,7 +3995,10 @@ class SsaBuilder extends ast.Visitor |
ast.NodeList arguments, |
CallStructure callStructure, |
_) { |
- generateCallInvoke(node, localsHandler.readLocal(function)); |
+ generateCallInvoke( |
+ node, |
+ localsHandler.readLocal(function), |
+ sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
} |
@override |
@@ -3933,7 +4008,8 @@ class SsaBuilder extends ast.Visitor |
ast.NodeList arguments, |
CallStructure callStructure, |
_) { |
- generateCallInvoke(node, localsHandler.readLocal(function)); |
+ generateCallInvoke(node, localsHandler.readLocal(function), |
+ sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
} |
void handleForeignJs(ast.Send node) { |
@@ -3953,17 +4029,21 @@ class SsaBuilder extends ast.Visitor |
TypeMask ssaType = |
TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); |
+ SourceInformation sourceInformation = |
+ sourceInformationBuilder.buildCall(node, node.argumentsNode); |
if (nativeBehavior.codeTemplate.isExpression) { |
push(new HForeignCode( |
nativeBehavior.codeTemplate, ssaType, inputs, |
effects: nativeBehavior.sideEffects, |
- nativeBehavior: nativeBehavior)); |
+ nativeBehavior: nativeBehavior) |
+ ..sourceInformation = sourceInformation); |
} else { |
push(new HForeignCode( |
nativeBehavior.codeTemplate, ssaType, inputs, |
isStatement: true, |
effects: nativeBehavior.sideEffects, |
- nativeBehavior: nativeBehavior)); |
+ nativeBehavior: nativeBehavior) |
+ ..sourceInformation = sourceInformation); |
} |
} |
@@ -4312,7 +4392,9 @@ class SsaBuilder extends ast.Visitor |
} |
} |
- generateDeferredLoaderGet(ast.Send node, FunctionElement deferredLoader) { |
+ generateDeferredLoaderGet(ast.Send node, |
+ FunctionElement deferredLoader, |
+ SourceInformation sourceInformation) { |
// Until now we only handle these as getters. |
invariant(node, deferredLoader.isDeferredLoaderGetter); |
Element loadFunction = compiler.loadLibraryFunction; |
@@ -4322,7 +4404,8 @@ class SsaBuilder extends ast.Visitor |
var inputs = [graph.addConstantString( |
new ast.DartString.literal(loadId), compiler)]; |
push(new HInvokeStatic(loadFunction, inputs, backend.nonNullType, |
- targetCanThrow: false)); |
+ targetCanThrow: false) |
+ ..sourceInformation = sourceInformation); |
} |
generateSuperNoSuchMethodSend(ast.Send node, |
@@ -4371,14 +4454,16 @@ class SsaBuilder extends ast.Visitor |
graph.addConstant(kindConstant, compiler), |
argumentsInstruction, |
argumentNamesInstruction], |
- typeMask: backend.dynamicType); |
+ typeMask: backend.dynamicType); |
var inputs = <HInstruction>[pop()]; |
push(buildInvokeSuper(compiler.noSuchMethodSelector, element, inputs)); |
} |
/// Generate a call to a super method or constructor. |
- void generateSuperInvoke(ast.Send node, FunctionElement function) { |
+ void generateSuperInvoke(ast.Send node, |
+ FunctionElement function, |
+ SourceInformation sourceInformation) { |
// TODO(5347): Try to avoid the need for calling [implementation] before |
// calling [makeStaticArgumentList]. |
Selector selector = elements.getSelector(node); |
@@ -4389,29 +4474,37 @@ class SsaBuilder extends ast.Visitor |
makeStaticArgumentList(selector.callStructure, |
node.arguments, |
function.implementation); |
- push(buildInvokeSuper(selector, function, inputs)); |
+ push(buildInvokeSuper(selector, function, inputs, sourceInformation)); |
} |
/// Access the value from the super [element]. |
void handleSuperGet(ast.Send node, Element element) { |
Selector selector = elements.getSelector(node); |
- push(buildInvokeSuper(selector, element, const <HInstruction>[])); |
+ SourceInformation sourceInformation = |
+ sourceInformationBuilder.buildGet(node); |
+ push(buildInvokeSuper( |
+ selector, element, const <HInstruction>[], sourceInformation)); |
} |
/// Invoke .call on the value retrieved from the super [element]. |
void handleSuperCallInvoke(ast.Send node, Element element) { |
Selector selector = elements.getSelector(node); |
- HInstruction target = |
- buildInvokeSuper(selector, element, const <HInstruction>[]); |
+ HInstruction target = buildInvokeSuper( |
+ selector, element, const <HInstruction>[], |
+ sourceInformationBuilder.buildGet(node)); |
add(target); |
- generateCallInvoke(node, target); |
+ generateCallInvoke( |
+ node, |
+ target, |
+ sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
} |
/// Invoke super [method]. |
void handleSuperMethodInvoke( |
ast.Send node, |
MethodElement method) { |
- generateSuperInvoke(node, method); |
+ generateSuperInvoke(node, method, |
+ sourceInformationBuilder.buildCall(node, node.selector)); |
} |
/// Access an unresolved super property. |
@@ -4622,8 +4715,10 @@ class SsaBuilder extends ast.Visitor |
* extract the type argument by the index of the variable in the list of type |
* variables for that class. |
*/ |
- HInstruction readTypeVariable(ClassElement cls, |
- TypeVariableElement variable) { |
+ HInstruction readTypeVariable( |
+ ClassElement cls, |
+ TypeVariableElement variable, |
+ {SourceInformation sourceInformation}) { |
assert(sourceElement.isInstanceMember); |
HInstruction target = localsHandler.readThis(); |
@@ -4641,11 +4736,15 @@ class SsaBuilder extends ast.Visitor |
pushInvokeStatic(null, |
backend.getGetRuntimeTypeArgument(), |
[target, substitutionNameInstr, index], |
- typeMask: backend.dynamicType); |
+ typeMask: backend.dynamicType, |
+ sourceInformation: sourceInformation); |
} else { |
- pushInvokeStatic(null, backend.getGetTypeArgumentByIndex(), |
+ pushInvokeStatic( |
+ null, |
+ backend.getGetTypeArgumentByIndex(), |
[target, index], |
- typeMask: backend.dynamicType); |
+ typeMask: backend.dynamicType, |
+ sourceInformation: sourceInformation); |
} |
return pop(); |
} |
@@ -4661,7 +4760,10 @@ class SsaBuilder extends ast.Visitor |
/** |
* Helper to create an instruction that gets the value of a type variable. |
*/ |
- HInstruction addTypeVariableReference(TypeVariableType type) { |
+ HInstruction addTypeVariableReference( |
+ TypeVariableType type, |
+ {SourceInformation sourceInformation}) { |
+ |
assert(assertTypeInContext(type)); |
Element member = sourceElement; |
bool isClosure = member.enclosingElement.isClosure; |
@@ -4679,14 +4781,18 @@ class SsaBuilder extends ast.Visitor |
// The type variable is used from a closure in a factory constructor. |
// The value of the type argument is stored as a local on the closure |
// itself. |
- return localsHandler.readLocal(typeVariableLocal); |
+ return localsHandler.readLocal( |
+ typeVariableLocal, sourceInformation: sourceInformation); |
} else if (member.isFunction || |
member.isGetter || |
member.isSetter || |
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); |
+ return readTypeVariable( |
+ member.enclosingClass, |
+ type.element, |
+ sourceInformation: sourceInformation); |
} else { |
assert(member.isField); |
// The type variable is stored in a parameter of the method. |
@@ -4700,11 +4806,14 @@ class SsaBuilder extends ast.Visitor |
// always return true when seeing one. |
(member.isField && !isBuildingFor(member))) { |
// The type variable is stored in a parameter of the method. |
- return localsHandler.readLocal(typeVariableLocal); |
+ return localsHandler.readLocal( |
+ typeVariableLocal, sourceInformation: sourceInformation); |
} else if (member.isInstanceMember) { |
// The type variable is stored on the object. |
- return readTypeVariable(member.enclosingClass, |
- type.element); |
+ return readTypeVariable( |
+ member.enclosingClass, |
+ type.element, |
+ sourceInformation: sourceInformation); |
} else { |
compiler.internalError(type.element, |
'Unexpected type variable in static context.'); |
@@ -4712,7 +4821,10 @@ class SsaBuilder extends ast.Visitor |
} |
} |
- HInstruction analyzeTypeArgument(DartType argument) { |
+ HInstruction analyzeTypeArgument( |
+ DartType argument, |
+ {SourceInformation sourceInformation}) { |
+ |
assert(assertTypeInContext(argument)); |
if (argument.treatAsDynamic) { |
// Represent [dynamic] as [null]. |
@@ -4720,7 +4832,8 @@ class SsaBuilder extends ast.Visitor |
} |
if (argument.isTypeVariable) { |
- return addTypeVariableReference(argument); |
+ return addTypeVariableReference( |
+ argument, sourceInformation: sourceInformation); |
} |
List<HInstruction> inputs = <HInstruction>[]; |
@@ -4755,7 +4868,8 @@ class SsaBuilder extends ast.Visitor |
void copyRuntimeTypeInfo(HInstruction source, HInstruction target) { |
Element copyHelper = backend.getCopyTypeArguments(); |
- pushInvokeStatic(null, copyHelper, [source, target]); |
+ pushInvokeStatic(null, copyHelper, [source, target], |
+ sourceInformation: target.sourceInformation); |
pop(); |
} |
@@ -4775,7 +4889,8 @@ class SsaBuilder extends ast.Visitor |
null, |
typeInfoSetterElement, |
<HInstruction>[newObject, typeInfo], |
- typeMask: backend.dynamicType); |
+ typeMask: backend.dynamicType, |
+ sourceInformation: newObject.sourceInformation); |
// The new object will now be referenced through the |
// `setRuntimeTypeInfo` call. We therefore set the type of that |
@@ -4933,6 +5048,8 @@ class SsaBuilder extends ast.Visitor |
push(buildLiteralList(<HInstruction>[])); |
stack.last.instructionType = elementType; |
} else { |
+ SourceInformation sourceInformation = |
+ sourceInformationBuilder.buildNew(send); |
ClassElement cls = constructor.enclosingClass; |
if (cls.isAbstract && constructor.isGenerativeConstructor) { |
generateAbstractClassInstantiationError(send, cls.name); |
@@ -4942,7 +5059,9 @@ class SsaBuilder extends ast.Visitor |
addInlinedInstantiation(expectedType); |
pushInvokeStatic(node, constructor, inputs, |
- typeMask: elementType, instanceType: expectedType); |
+ typeMask: elementType, |
+ instanceType: expectedType, |
+ sourceInformation: sourceInformation); |
removeInlinedInstantiation(expectedType); |
} |
HInstruction newInstance = stack.last; |
@@ -4976,12 +5095,14 @@ class SsaBuilder extends ast.Visitor |
} |
void potentiallyAddTypeArguments(List<HInstruction> inputs, ClassElement cls, |
- InterfaceType expectedType) { |
+ InterfaceType expectedType, |
+ {SourceInformation sourceInformation}) { |
if (!backend.classNeedsRti(cls)) return; |
assert(expectedType.typeArguments.isEmpty || |
cls.typeVariables.length == expectedType.typeArguments.length); |
expectedType.typeArguments.forEach((DartType argument) { |
- inputs.add(analyzeTypeArgument(argument)); |
+ inputs.add(analyzeTypeArgument( |
+ argument, sourceInformation: sourceInformation)); |
}); |
} |
@@ -5074,7 +5195,9 @@ class SsaBuilder extends ast.Visitor |
new HIdentity(inputs[0], inputs[1], null, backend.boolType), node); |
return; |
} else { |
- pushInvokeStatic(node, function, inputs); |
+ pushInvokeStatic(node, function, inputs, |
+ sourceInformation: sourceInformationBuilder.buildCall( |
+ node, node.selector)); |
} |
} |
@@ -5093,7 +5216,10 @@ class SsaBuilder extends ast.Visitor |
CallStructure callStructure, |
_) { |
generateStaticFieldGet(node, field); |
- generateCallInvoke(node, pop()); |
+ generateCallInvoke( |
+ node, |
+ pop(), |
+ sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
} |
@override |
@@ -5124,7 +5250,10 @@ class SsaBuilder extends ast.Visitor |
CallStructure callStructure, |
_) { |
generateStaticGetterGet(node, getter); |
- generateCallInvoke(node, pop()); |
+ generateCallInvoke( |
+ node, |
+ pop(), |
+ sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
} |
@override |
@@ -5135,7 +5264,10 @@ class SsaBuilder extends ast.Visitor |
CallStructure callStructure, |
_) { |
generateStaticFieldGet(node, field); |
- generateCallInvoke(node, pop()); |
+ generateCallInvoke( |
+ node, |
+ pop(), |
+ sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
} |
@override |
@@ -5170,7 +5302,10 @@ class SsaBuilder extends ast.Visitor |
CallStructure callStructure, |
_) { |
generateStaticGetterGet(node, getter); |
- generateCallInvoke(node, pop()); |
+ generateCallInvoke( |
+ node, |
+ pop(), |
+ sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
} |
@override |
@@ -5335,7 +5470,8 @@ class SsaBuilder extends ast.Visitor |
void generateTypeVariableLiteral(ast.Send node, |
TypeVariableType typeVariable) { |
DartType type = localsHandler.substInContext(typeVariable); |
- HInstruction value = analyzeTypeArgument(type); |
+ HInstruction value = analyzeTypeArgument(type, |
+ sourceInformation: sourceInformationBuilder.buildGet(node)); |
pushInvokeStatic(node, |
backend.getRuntimeTypeToString(), |
[value], |
@@ -5352,19 +5488,21 @@ class SsaBuilder extends ast.Visitor |
// reference instead of creating a NoSuchMethodError to avoid pulling it |
// in if it is not used (e.g., in a try/catch). |
HInstruction target = pop(); |
- generateCallInvoke(node, target); |
+ generateCallInvoke(node, target, |
+ sourceInformationBuilder.buildCall(node, node.argumentsNode)); |
} |
/// Generate a '.call' invocation on [target]. |
- void generateCallInvoke(ast.Send node, HInstruction target) { |
+ void generateCallInvoke(ast.Send node, |
+ HInstruction target, |
+ SourceInformation sourceInformation) { |
Selector selector = elements.getSelector(node); |
List<HInstruction> inputs = <HInstruction>[target]; |
addDynamicSendArgumentsToList(node, inputs); |
- pushWithPosition( |
- new HInvokeClosure( |
+ push(new HInvokeClosure( |
new Selector.callClosureFrom(selector), |
- inputs, backend.dynamicType), |
- node); |
+ inputs, backend.dynamicType) |
+ ..sourceInformation = sourceInformation); |
} |
visitGetterSend(ast.Send node) { |
@@ -5399,7 +5537,8 @@ class SsaBuilder extends ast.Visitor |
String methodName, |
{Link<ast.Node> argumentNodes, |
List<HInstruction> argumentValues, |
- List<String> existingArguments}) { |
+ List<String> existingArguments, |
+ SourceInformation sourceInformation}) { |
Element helper = backend.getThrowNoSuchMethod(); |
ConstantValue receiverConstant = |
constantSystem.createString(new ast.DartString.empty()); |
@@ -5432,7 +5571,8 @@ class SsaBuilder extends ast.Visitor |
} |
pushInvokeStatic(diagnosticNode, |
helper, |
- [receiver, name, arguments, existingNamesList]); |
+ [receiver, name, arguments, existingNamesList], |
+ sourceInformation: sourceInformation); |
} |
/** |
@@ -5511,8 +5651,7 @@ class SsaBuilder extends ast.Visitor |
Selector selector, |
TypeMask mask, |
List<HInstruction> arguments, |
- {ast.Node location}) { |
- if (location == null) location = node; |
+ {SourceInformation sourceInformation}) { |
// We prefer to not inline certain operations on indexables, |
// because the constant folder will handle them better and turn |
@@ -5571,17 +5710,17 @@ class SsaBuilder extends ast.Visitor |
TypeMask type = |
TypeMaskFactory.inferredTypeForSelector(selector, mask, compiler); |
if (selector.isGetter) { |
- pushWithPosition( |
- new HInvokeDynamicGetter(selector, mask, null, inputs, type), |
- location); |
+ push( |
+ new HInvokeDynamicGetter(selector, mask, null, inputs, type) |
+ ..sourceInformation = sourceInformation); |
} else if (selector.isSetter) { |
- pushWithPosition( |
- new HInvokeDynamicSetter(selector, mask, null, inputs, type), |
- location); |
+ push( |
+ new HInvokeDynamicSetter(selector, mask, null, inputs, type) |
+ ..sourceInformation = sourceInformation); |
} else { |
- pushWithPosition( |
- new HInvokeDynamicMethod(selector, mask, inputs, type, isIntercepted), |
- location); |
+ push( |
+ new HInvokeDynamicMethod(selector, mask, inputs, type, isIntercepted) |
+ ..sourceInformation = sourceInformation); |
} |
} |
@@ -5589,7 +5728,9 @@ class SsaBuilder extends ast.Visitor |
Element element, |
List<HInstruction> arguments, |
{TypeMask typeMask, |
- InterfaceType instanceType}) { |
+ InterfaceType instanceType, |
+ SourceInformation sourceInformation}) { |
+ // TODO(johnniwinther): Use [sourceInformation] instead of [location]. |
if (tryInlineMethod(element, null, null, arguments, location, |
instanceType: instanceType)) { |
return; |
@@ -5604,7 +5745,8 @@ class SsaBuilder extends ast.Visitor |
// creating an [HInvokeStatic]. |
HInvokeStatic instruction = new HInvokeStatic( |
element.declaration, arguments, typeMask, |
- targetCanThrow: targetCanThrow); |
+ targetCanThrow: targetCanThrow) |
+ ..sourceInformation = sourceInformation; |
if (!currentInlinedInstantiations.isEmpty) { |
instruction.instantiatedTypes = new List<DartType>.from( |
currentInlinedInstantiations); |
@@ -5619,7 +5761,8 @@ class SsaBuilder extends ast.Visitor |
HInstruction buildInvokeSuper(Selector selector, |
Element element, |
- List<HInstruction> arguments) { |
+ List<HInstruction> arguments, |
+ [SourceInformation sourceInformation]) { |
HInstruction receiver = localsHandler.readThis(); |
// TODO(5346): Try to avoid the need for calling [declaration] before |
// creating an [HStatic]. |
@@ -5644,6 +5787,7 @@ class SsaBuilder extends ast.Visitor |
selector, |
inputs, |
type, |
+ sourceInformation, |
isSetter: selector.isSetter || selector.isIndexSet); |
instruction.sideEffects = |
compiler.world.getSideEffectsOfSelector(selector, null); |
@@ -5661,11 +5805,14 @@ class SsaBuilder extends ast.Visitor |
assert(arguments.tail.isEmpty); |
rhs = pop(); |
} |
- visitBinarySend(receiver, rhs, |
- elements.getOperatorSelectorInComplexSendSet(node), |
- elements.getOperatorTypeMaskInComplexSendSet(node), |
- node, |
- location: node.assignmentOperator); |
+ visitBinarySend( |
+ receiver, |
+ rhs, |
+ elements.getOperatorSelectorInComplexSendSet(node), |
+ elements.getOperatorTypeMaskInComplexSendSet(node), |
+ node, |
+ sourceInformation: |
+ sourceInformationBuilder.buildGeneric(node.assignmentOperator)); |
} |
void handleSuperSendSet(ast.SendSet node) { |
@@ -6525,7 +6672,7 @@ class SsaBuilder extends ast.Visitor |
} else if (getter.isFunction) { |
generateStaticFunctionGet(node, getter); |
} else if (getter.isLocal) { |
- handleLocalGet(getter); |
+ handleLocalGet(node, getter); |
} else { |
internalError(node, "Unexpected getter: $getter"); |
} |
@@ -6665,7 +6812,10 @@ class SsaBuilder extends ast.Visitor |
'rethrowableException should not be null.'); |
} |
handleInTryStatement(); |
- closeAndGotoExit(new HThrow(exception, isRethrow: true)); |
+ closeAndGotoExit( |
+ new HThrow(exception, |
+ sourceInformationBuilder.buildThrow(node), |
+ isRethrow: true)); |
} |
visitRedirectingFactoryBody(ast.RedirectingFactoryBody node) { |
@@ -6762,7 +6912,8 @@ class SsaBuilder extends ast.Visitor |
visitThrowExpression(node.expression); |
if (isReachable) { |
handleInTryStatement(); |
- push(new HThrowExpression(pop())); |
+ push(new HThrowExpression( |
+ pop(), sourceInformationBuilder.buildThrow(node))); |
isReachable = false; |
} |
} |
@@ -7536,7 +7687,10 @@ class SsaBuilder extends ast.Visitor |
[localsHandler.readLocal(switchTarget)], |
nativeBehavior: native.NativeBehavior.PURE)); |
} |
- handleIf(node, buildCondition, buildLoop, () => {}); |
+ handleIf(node, |
+ visitCondition: buildCondition, |
+ visitThen: buildLoop, |
+ visitElse: () => {}); |
} |
} |
@@ -7599,7 +7753,7 @@ class SsaBuilder extends ast.Visitor |
if (caseIterator.hasNext) { |
pushInvokeStatic(switchCase, getFallThroughErrorElement, []); |
HInstruction error = pop(); |
- closeAndGotoExit(new HThrow(error)); |
+ closeAndGotoExit(new HThrow(error, error.sourceInformation)); |
} else if (!isDefaultCase(switchCase)) { |
// If there is no default, we will add one later to avoid |
// the critical edge. So we generate a break statement to make |
@@ -7875,17 +8029,24 @@ class SsaBuilder extends ast.Visitor |
void visitElse() { |
if (link.isEmpty) { |
- closeAndGotoExit(new HThrow(exception, isRethrow: true)); |
+ closeAndGotoExit( |
+ new HThrow(exception, |
+ exception.sourceInformation, |
+ isRethrow: true)); |
} else { |
ast.CatchBlock newBlock = link.head; |
handleIf(node, |
- () { pushCondition(newBlock); }, |
- visitThen, visitElse); |
+ visitCondition: () { pushCondition(newBlock); }, |
+ visitThen: visitThen, |
+ visitElse: visitElse); |
} |
} |
ast.CatchBlock firstBlock = link.head; |
- handleIf(node, () { pushCondition(firstBlock); }, visitThen, visitElse); |
+ handleIf(node, |
+ visitCondition: () { pushCondition(firstBlock); }, |
+ visitThen: visitThen, |
+ visitElse: visitElse); |
if (!isAborted()) endCatchBlock = close(new HGoto()); |
rethrowableException = oldRethrowableException; |
@@ -8016,7 +8177,8 @@ class SsaBuilder extends ast.Visitor |
void emitReturn(HInstruction value, ast.Node node) { |
if (inliningStack.isEmpty) { |
- closeAndGotoExit(attachPosition(new HReturn(value), node)); |
+ closeAndGotoExit(new HReturn(value, |
+ sourceInformationBuilder.buildReturn(node))); |
} else { |
localsHandler.updateLocal(returnLocal, value); |
} |
@@ -8375,13 +8537,14 @@ class SsaBranchBuilder { |
void buildCondition(void visitCondition(), |
SsaBranch conditionBranch, |
SsaBranch thenBranch, |
- SsaBranch elseBranch) { |
+ SsaBranch elseBranch, |
+ SourceInformation sourceInformation) { |
startBranch(conditionBranch); |
visitCondition(); |
checkNotAborted(); |
assert(identical(builder.current, builder.lastOpenedBlock)); |
HInstruction conditionValue = builder.popBoolified(); |
- HIf branch = new HIf(conditionValue); |
+ HIf branch = new HIf(conditionValue)..sourceInformation = sourceInformation; |
HBasicBlock conditionExitBlock = builder.current; |
builder.close(branch); |
conditionBranch.exitLocals = builder.localsHandler; |
@@ -8442,7 +8605,10 @@ class SsaBranchBuilder { |
return null; |
} |
- handleIf(void visitCondition(), void visitThen(), void visitElse()) { |
+ handleIf(void visitCondition(), |
+ void visitThen(), |
+ void visitElse(), |
+ {SourceInformation sourceInformation}) { |
if (visitElse == null) { |
// Make sure to have an else part to avoid a critical edge. A |
// critical edge is an edge that connects a block with multiple |
@@ -8452,12 +8618,17 @@ class SsaBranchBuilder { |
visitElse = () {}; |
} |
- _handleDiamondBranch(visitCondition, visitThen, visitElse, false); |
+ _handleDiamondBranch( |
+ visitCondition, visitThen, visitElse, isExpression: false, |
+ sourceInformation: sourceInformation); |
} |
- handleConditional(void visitCondition(), void visitThen(), void visitElse()) { |
+ handleConditional(void visitCondition(), |
+ void visitThen(), |
+ void visitElse()) { |
assert(visitElse != null); |
- _handleDiamondBranch(visitCondition, visitThen, visitElse, true); |
+ _handleDiamondBranch( |
+ visitCondition, visitThen, visitElse, isExpression: true); |
} |
handleIfNull(void left(), void right()) { |
@@ -8552,7 +8723,8 @@ class SsaBranchBuilder { |
void _handleDiamondBranch(void visitCondition(), |
void visitThen(), |
void visitElse(), |
- bool isExpression) { |
+ {bool isExpression, |
+ SourceInformation sourceInformation}) { |
SsaBranch conditionBranch = new SsaBranch(this); |
SsaBranch thenBranch = new SsaBranch(this); |
SsaBranch elseBranch = new SsaBranch(this); |
@@ -8561,7 +8733,8 @@ class SsaBranchBuilder { |
conditionBranch.startLocals = builder.localsHandler; |
builder.goto(builder.current, conditionBranch.block); |
- buildCondition(visitCondition, conditionBranch, thenBranch, elseBranch); |
+ buildCondition(visitCondition, conditionBranch, thenBranch, elseBranch, |
+ sourceInformation); |
HInstruction thenValue = |
buildBranch(thenBranch, visitThen, joinBranch, isExpression); |
HInstruction elseValue = |