| Index: pkg/compiler/lib/src/ssa/codegen.dart
|
| diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
|
| index 2524fdfcaf0e785fb0e1eff368976aecc6e7a96a..6057d6f42e863dc7db5cadaf37af619a2a82f30b 100644
|
| --- a/pkg/compiler/lib/src/ssa/codegen.dart
|
| +++ b/pkg/compiler/lib/src/ssa/codegen.dart
|
| @@ -7,7 +7,7 @@ part of ssa;
|
| class SsaCodeGeneratorTask extends CompilerTask {
|
|
|
| final JavaScriptBackend backend;
|
| - final SourceInformationFactory sourceInformationFactory;
|
| + final SourceInformationStrategy sourceInformationFactory;
|
|
|
| SsaCodeGeneratorTask(JavaScriptBackend backend,
|
| this.sourceInformationFactory)
|
| @@ -17,12 +17,6 @@ class SsaCodeGeneratorTask extends CompilerTask {
|
| String get name => 'SSA code generator';
|
| NativeEmitter get nativeEmitter => backend.emitter.nativeEmitter;
|
|
|
| -
|
| - js.Node attachPosition(js.Node node, AstElement element) {
|
| - return node.withSourceInformation(
|
| - StartEndSourceInformation.computeSourceInformation(element));
|
| - }
|
| -
|
| js.Fun buildJavaScriptFunction(FunctionElement element,
|
| List<js.Parameter> parameters,
|
| js.Block body) {
|
| @@ -35,8 +29,9 @@ class SsaCodeGeneratorTask extends CompilerTask {
|
| : const js.AsyncModifier.sync());
|
|
|
| return new js.Fun(parameters, body, asyncModifier: asyncModifier)
|
| - .withSourceInformation(sourceInformationFactory.forContext(element)
|
| - .buildDeclaration(element));
|
| + .withSourceInformation(
|
| + sourceInformationFactory.createBuilderForContext(element)
|
| + .buildDeclaration(element));
|
| }
|
|
|
| js.Expression generateCode(CodegenWorkItem work, HGraph graph) {
|
| @@ -51,7 +46,7 @@ class SsaCodeGeneratorTask extends CompilerTask {
|
| return measure(() {
|
| compiler.tracer.traceGraph("codegen", graph);
|
| SourceInformation sourceInformation =
|
| - sourceInformationFactory.forContext(work.element)
|
| + sourceInformationFactory.createBuilderForContext(work.element)
|
| .buildDeclaration(work.element);
|
| SsaCodeGenerator codegen = new SsaCodeGenerator(backend, work);
|
| codegen.visitGraph(graph);
|
| @@ -189,11 +184,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| * If the [instruction] is not `null` it will be used to attach the position
|
| * to the [statement].
|
| */
|
| - void pushStatement(js.Statement statement, [HInstruction instruction]) {
|
| + void pushStatement(js.Statement statement) {
|
| assert(expressionStack.isEmpty);
|
| - if (instruction != null) {
|
| - statement = attachLocation(statement, instruction);
|
| - }
|
| currentContainer.statements.add(statement);
|
| }
|
|
|
| @@ -206,18 +198,16 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| * to the [expression].
|
| */
|
| pushExpressionAsStatement(js.Expression expression,
|
| - [HInstruction instruction]) {
|
| - pushStatement(new js.ExpressionStatement(expression), instruction);
|
| + SourceInformation sourceInformation) {
|
| + pushStatement(new js.ExpressionStatement(expression)
|
| + .withSourceInformation(sourceInformation));
|
| }
|
|
|
| /**
|
| * If the [instruction] is not `null` it will be used to attach the position
|
| * to the [expression].
|
| */
|
| - push(js.Expression expression, [HInstruction instruction]) {
|
| - if (instruction != null) {
|
| - expression = attachLocation(expression, instruction);
|
| - }
|
| + push(js.Expression expression) {
|
| expressionStack.add(expression);
|
| }
|
|
|
| @@ -225,21 +215,6 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| return expressionStack.removeLast();
|
| }
|
|
|
| - attachLocationToLast(HInstruction instruction) {
|
| - int index = expressionStack.length - 1;
|
| - expressionStack[index] =
|
| - attachLocation(expressionStack[index], instruction);
|
| - }
|
| -
|
| - js.Node attachLocation(js.Node jsNode, HInstruction instruction) {
|
| - return attachSourceInformation(jsNode, instruction.sourceInformation);
|
| - }
|
| -
|
| - js.Node attachSourceInformation(js.Node jsNode,
|
| - SourceInformation sourceInformation) {
|
| - return jsNode.withSourceInformation(sourceInformation);
|
| - }
|
| -
|
| void preGenerateMethod(HGraph graph) {
|
| new SsaInstructionSelection(compiler).visitGraph(graph);
|
| new SsaTypeKnownRemover().visitGraph(graph);
|
| @@ -499,10 +474,13 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| }
|
| }
|
| }
|
| - return new js.Assignment(new js.VariableUse(variableName), value);
|
| + return new js.Assignment(new js.VariableUse(variableName), value)
|
| + .withSourceInformation(value.sourceInformation);
|
| }
|
|
|
| - void assignVariable(String variableName, js.Expression value) {
|
| + void assignVariable(String variableName,
|
| + js.Expression value,
|
| + SourceInformation sourceInformation) {
|
| if (isGeneratingExpression) {
|
| // If we are in an expression then we can't declare the variable here.
|
| // We have no choice, but to use it and then declare it separately.
|
| @@ -522,7 +500,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| new js.VariableInitialization(decl, value);
|
|
|
| pushExpressionAsStatement(new js.VariableDeclarationList(
|
| - <js.VariableInitialization>[initialization]));
|
| + <js.VariableInitialization>[initialization]),
|
| + sourceInformation);
|
| } else {
|
| // Otherwise we are just going to use it. If we have not already declared
|
| // it then we make sure we will declare it later.
|
| @@ -530,7 +509,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| collectedVariableDeclarations.add(variableName);
|
| }
|
| pushExpressionAsStatement(
|
| - generateExpressionAssignment(variableName, value));
|
| + generateExpressionAssignment(variableName, value),
|
| + sourceInformation);
|
| }
|
| }
|
|
|
| @@ -553,7 +533,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| if (needsAssignment &&
|
| !instruction.isControlFlow() && variableNames.hasName(instruction)) {
|
| visitExpression(instruction);
|
| - assignVariable(variableNames.getName(instruction), pop());
|
| + assignVariable(variableNames.getName(instruction), pop(),
|
| + instruction.sourceInformation);
|
| return;
|
| }
|
|
|
| @@ -594,7 +575,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| visit(node);
|
| if (!expressionStack.isEmpty) {
|
| assert(expressionStack.length == 1);
|
| - pushExpressionAsStatement(pop());
|
| + js.Expression expression = pop();
|
| + pushExpressionAsStatement(expression, node.sourceInformation);
|
| }
|
| }
|
|
|
| @@ -611,7 +593,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| pushStatement(new js.Break(backend.namer.implicitBreakLabelName(target)));
|
| }
|
|
|
| - js.Statement wrapIntoLabels(js.Statement result, List<LabelDefinition> labels) {
|
| + js.Statement wrapIntoLabels(js.Statement result,
|
| + List<LabelDefinition> labels) {
|
| for (LabelDefinition label in labels) {
|
| if (label.isTarget) {
|
| String breakLabelString = backend.namer.breakLabelName(label);
|
| @@ -834,7 +817,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| visitBodyIgnoreLabels(info);
|
| currentContainer = oldContainer;
|
| body = unwrapStatement(body);
|
| - loop = new js.For(jsInitialization, jsCondition, jsUpdates, body);
|
| + loop = new js.For(jsInitialization, jsCondition, jsUpdates, body)
|
| + .withSourceInformation(info.sourceInformation);
|
| } else {
|
| // We have either no update graph, or it's too complex to
|
| // put in an expression.
|
| @@ -848,7 +832,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| jsCondition = generateExpression(condition);
|
| currentContainer = body;
|
| } else {
|
| - jsCondition = newLiteralBool(true);
|
| + jsCondition = newLiteralBool(true, info.sourceInformation);
|
| currentContainer = body;
|
| generateStatements(condition);
|
| use(condition.conditionExpression);
|
| @@ -871,7 +855,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| }
|
| currentContainer = oldContainer;
|
| body = unwrapStatement(body);
|
| - loop = new js.While(jsCondition, body);
|
| + loop = new js.While(jsCondition, body)
|
| + .withSourceInformation(info.sourceInformation);
|
| }
|
| break;
|
| case HLoopBlockInformation.DO_WHILE_LOOP:
|
| @@ -922,7 +907,10 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| // If the condition is dead code, we turn the do-while into
|
| // a simpler while because we will never reach the condition
|
| // at the end of the loop anyway.
|
| - loop = new js.While(newLiteralBool(true), unwrapStatement(body));
|
| + loop = new js.While(
|
| + newLiteralBool(true, info.sourceInformation),
|
| + unwrapStatement(body))
|
| + .withSourceInformation(info.sourceInformation);
|
| } else {
|
| if (hasPhiUpdates || hasExitPhiUpdates) {
|
| updateBody.statements.add(new js.Continue(null));
|
| @@ -936,9 +924,10 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| }
|
| body.statements.add(
|
| new js.If(jsCondition, updateBody, exitLoop));
|
| - jsCondition = newLiteralBool(true);
|
| + jsCondition = newLiteralBool(true, info.sourceInformation);
|
| }
|
| - loop = new js.Do(unwrapStatement(body), jsCondition);
|
| + loop = new js.Do(unwrapStatement(body), jsCondition)
|
| + .withSourceInformation(info.sourceInformation);
|
| }
|
| currentContainer = oldContainer;
|
| break;
|
| @@ -946,7 +935,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| compiler.internalError(condition.conditionExpression,
|
| 'Unexpected loop kind: ${info.kind}.');
|
| }
|
| - js.Statement result = attachSourceInformation(loop, info.sourceInformation);
|
| + js.Statement result = loop;
|
| if (info.kind == HLoopBlockInformation.SWITCH_CONTINUE_LOOP) {
|
| String continueLabelString =
|
| backend.namer.implicitContinueLabelName(info.target);
|
| @@ -1093,7 +1082,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| }
|
|
|
| void emitAssignment(String destination, String source) {
|
| - assignVariable(destination, new js.VariableUse(source));
|
| + assignVariable(destination, new js.VariableUse(source), null);
|
| }
|
|
|
| /**
|
| @@ -1193,7 +1182,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| for (Copy copy in handler.assignments) {
|
| String name = variableNames.getName(copy.destination);
|
| use(copy.source);
|
| - assignVariable(name, pop());
|
| + assignVariable(name, pop(), null);
|
| }
|
| }
|
|
|
| @@ -1209,27 +1198,38 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| visit(instruction);
|
| }
|
|
|
| - visitInvokeBinary(HInvokeBinary node, String op) {
|
| + void handleInvokeBinary(HInvokeBinary node,
|
| + String op,
|
| + SourceInformation sourceInformation) {
|
| use(node.left);
|
| js.Expression jsLeft = pop();
|
| use(node.right);
|
| - push(new js.Binary(op, jsLeft, pop()), node);
|
| + push(new js.Binary(op, jsLeft, pop())
|
| + .withSourceInformation(sourceInformation));
|
| + }
|
| +
|
| + visitInvokeBinary(HInvokeBinary node, String op) {
|
| + handleInvokeBinary(node, op, node.sourceInformation);
|
| }
|
|
|
| - visitRelational(HRelational node, String op) => visitInvokeBinary(node, op);
|
| + visitRelational(HRelational node, String op) {
|
| + handleInvokeBinary(node, op, node.sourceInformation);
|
| + }
|
|
|
| // We want the outcome of bit-operations to be positive. We use the unsigned
|
| // shift operator to achieve this.
|
| visitBitInvokeBinary(HBinaryBitOp node, String op) {
|
| visitInvokeBinary(node, op);
|
| if (op != '>>>' && requiresUintConversion(node)) {
|
| - push(new js.Binary(">>>", pop(), new js.LiteralNumber("0")), node);
|
| + push(new js.Binary(">>>", pop(), new js.LiteralNumber("0"))
|
| + .withSourceInformation(node.sourceInformation));
|
| }
|
| }
|
|
|
| visitInvokeUnary(HInvokeUnary node, String op) {
|
| use(node.operand);
|
| - push(new js.Prefix(op, pop()), node);
|
| + push(new js.Prefix(op, pop())
|
| + .withSourceInformation(node.sourceInformation));
|
| }
|
|
|
| // We want the outcome of bit-operations to be positive. We use the unsigned
|
| @@ -1237,11 +1237,14 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| visitBitInvokeUnary(HInvokeUnary node, String op) {
|
| visitInvokeUnary(node, op);
|
| if (requiresUintConversion(node)) {
|
| - push(new js.Binary(">>>", pop(), new js.LiteralNumber("0")), node);
|
| + push(new js.Binary(">>>", pop(), new js.LiteralNumber("0"))
|
| + .withSourceInformation(node.sourceInformation));
|
| }
|
| }
|
|
|
| - void emitIdentityComparison(HIdentity instruction, bool inverse) {
|
| + void emitIdentityComparison(HIdentity instruction,
|
| + SourceInformation sourceInformation,
|
| + {bool inverse: false}) {
|
| String op = instruction.singleComparisonOp;
|
| HInstruction left = instruction.left;
|
| HInstruction right = instruction.right;
|
| @@ -1249,7 +1252,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| use(left);
|
| js.Expression jsLeft = pop();
|
| use(right);
|
| - push(new js.Binary(mapRelationalOperator(op, inverse), jsLeft, pop()));
|
| + push(new js.Binary(mapRelationalOperator(op, inverse), jsLeft, pop())
|
| + .withSourceInformation(sourceInformation));
|
| } else {
|
| assert(NullConstantValue.JsNull == 'null');
|
| use(left);
|
| @@ -1264,12 +1268,13 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| js.Binary tripleEq = new js.Binary(mapRelationalOperator("===", inverse),
|
| pop(), pop());
|
|
|
| - push(new js.Conditional(leftEqualsNull, rightEqualsNull, tripleEq));
|
| + push(new js.Conditional(leftEqualsNull, rightEqualsNull, tripleEq)
|
| + .withSourceInformation(sourceInformation));
|
| }
|
| }
|
|
|
| visitIdentity(HIdentity node) {
|
| - emitIdentityComparison(node, false);
|
| + emitIdentityComparison(node, node.sourceInformation, inverse: false);
|
| }
|
|
|
| visitAdd(HAdd node) => visitInvokeBinary(node, '+');
|
| @@ -1292,11 +1297,13 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| use(node.left);
|
| js.Expression jsLeft = pop();
|
| use(node.right);
|
| - push(new js.Binary('/', jsLeft, pop()), node);
|
| - push(new js.Binary('|', pop(), new js.LiteralNumber("0")), node);
|
| + push(new js.Binary('/', jsLeft, pop())
|
| + .withSourceInformation(node.sourceInformation));
|
| + push(new js.Binary('|', pop(), new js.LiteralNumber("0"))
|
| + .withSourceInformation(node.sourceInformation));
|
| }
|
|
|
| - visitNegate(HNegate node) => visitInvokeUnary(node, '-');
|
| + visitNegate(HNegate node) => visitInvokeUnary(node, '-');
|
|
|
| visitLess(HLess node) => visitRelational(node, '<');
|
| visitLessEqual(HLessEqual node) => visitRelational(node, '<=');
|
| @@ -1306,7 +1313,9 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| visitBoolify(HBoolify node) {
|
| assert(node.inputs.length == 1);
|
| use(node.inputs[0]);
|
| - push(new js.Binary('===', pop(), newLiteralBool(true)), node);
|
| + push(new js.Binary('===', pop(),
|
| + newLiteralBool(true, node.sourceInformation))
|
| + .withSourceInformation(node.sourceInformation));
|
| }
|
|
|
| visitExit(HExit node) {
|
| @@ -1362,16 +1371,20 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| if (node.label != null) {
|
| LabelDefinition label = node.label;
|
| if (!tryCallAction(breakAction, label)) {
|
| - pushStatement(new js.Break(backend.namer.breakLabelName(label)), node);
|
| + pushStatement(
|
| + new js.Break(backend.namer.breakLabelName(label))
|
| + .withSourceInformation(node.sourceInformation));
|
| }
|
| } else {
|
| JumpTarget target = node.target;
|
| if (!tryCallAction(breakAction, target)) {
|
| if (node.breakSwitchContinueLoop) {
|
| - pushStatement(new js.Break(
|
| - backend.namer.implicitContinueLabelName(target)), node);
|
| + pushStatement(
|
| + new js.Break(backend.namer.implicitContinueLabelName(target))
|
| + .withSourceInformation(node.sourceInformation));
|
| } else {
|
| - pushStatement(new js.Break(null), node);
|
| + pushStatement(new js.Break(null)
|
| + .withSourceInformation(node.sourceInformation));
|
| }
|
| }
|
| }
|
| @@ -1383,17 +1396,20 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| LabelDefinition label = node.label;
|
| if (!tryCallAction(continueAction, label)) {
|
| // TODO(floitsch): should this really be the breakLabelName?
|
| - pushStatement(new js.Continue(backend.namer.breakLabelName(label)),
|
| - node);
|
| + pushStatement(
|
| + new js.Continue(backend.namer.breakLabelName(label))
|
| + .withSourceInformation(node.sourceInformation));
|
| }
|
| } else {
|
| JumpTarget target = node.target;
|
| if (!tryCallAction(continueAction, target)) {
|
| if (target.statement is ast.SwitchStatement) {
|
| - pushStatement(new js.Continue(
|
| - backend.namer.implicitContinueLabelName(target)), node);
|
| + pushStatement(
|
| + new js.Continue(backend.namer.implicitContinueLabelName(target))
|
| + .withSourceInformation(node.sourceInformation));
|
| } else {
|
| - pushStatement(new js.Continue(null), node);
|
| + pushStatement(new js.Continue(null)
|
| + .withSourceInformation(node.sourceInformation));
|
| }
|
| }
|
| }
|
| @@ -1444,7 +1460,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| js.Statement elsePart =
|
| unwrapStatement(generateStatementsInNewBlock(elseGraph));
|
|
|
| - pushStatement(new js.If(test, thenPart, elsePart), node);
|
| + pushStatement(new js.If(test, thenPart, elsePart)
|
| + .withSourceInformation(node.sourceInformation));
|
| }
|
|
|
| visitIf(HIf node) {
|
| @@ -1499,7 +1516,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| backend.namer.globalObjectFor(backend.interceptorsLibrary));
|
| use(node.receiver);
|
| List<js.Expression> arguments = <js.Expression>[pop()];
|
| - push(js.propertyCall(isolate, name, arguments), node);
|
| + push(js.propertyCall(isolate, name, arguments)
|
| + .withSourceInformation(node.sourceInformation));
|
| registry.registerUseInterceptor();
|
| }
|
| }
|
| @@ -1538,7 +1556,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| } else {
|
| methodLiteral = backend.namer.asName(methodName);
|
| }
|
| - push(js.propertyCall(object, methodLiteral, arguments), node);
|
| + push(js.propertyCall(object, methodLiteral, arguments)
|
| + .withSourceInformation(node.sourceInformation));
|
| }
|
|
|
| void visitInvokeConstructorBody(HInvokeConstructorBody node) {
|
| @@ -1546,7 +1565,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| js.Expression object = pop();
|
| js.Name methodName = backend.namer.instanceMethodName(node.element);
|
| List<js.Expression> arguments = visitArguments(node.inputs);
|
| - push(js.propertyCall(object, methodName, arguments), node);
|
| + push(js.propertyCall(object, methodName, arguments)
|
| + .withSourceInformation(node.sourceInformation));
|
| registry.registerStaticUse(node.element);
|
| }
|
|
|
| @@ -1557,7 +1577,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| Selector selector = node.selector;
|
| TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask);
|
| js.Name methodName = backend.registerOneShotInterceptor(selector);
|
| - push(js.propertyCall(isolate, methodName, arguments), node);
|
| + push(js.propertyCall(isolate, methodName, arguments)
|
| + .withSourceInformation(node.sourceInformation));
|
| if (selector.isGetter) {
|
| registerGetter(node);
|
| } else if (selector.isSetter) {
|
| @@ -1622,14 +1643,16 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
|
| use(node.receiver);
|
| js.Name name = backend.namer.invocationName(node.selector);
|
| - push(js.propertyCall(pop(), name, visitArguments(node.inputs)), node);
|
| + push(js.propertyCall(pop(), name, visitArguments(node.inputs))
|
| + .withSourceInformation(node.sourceInformation));
|
| registerSetter(node);
|
| }
|
|
|
| visitInvokeDynamicGetter(HInvokeDynamicGetter node) {
|
| use(node.receiver);
|
| js.Name name = backend.namer.invocationName(node.selector);
|
| - push(js.propertyCall(pop(), name, visitArguments(node.inputs)), node);
|
| + push(js.propertyCall(pop(), name, visitArguments(node.inputs))
|
| + .withSourceInformation(node.sourceInformation));
|
| registerGetter(node);
|
| }
|
|
|
| @@ -1638,8 +1661,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| use(node.receiver);
|
| push(js.propertyCall(pop(),
|
| backend.namer.invocationName(call),
|
| - visitArguments(node.inputs)),
|
| - node);
|
| + visitArguments(node.inputs))
|
| + .withSourceInformation(node.sourceInformation));
|
| registry.registerDynamicInvocation(
|
| new UniverseSelector(call, null));
|
| }
|
| @@ -1681,7 +1704,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| } else {
|
| registry.registerStaticInvocation(element);
|
| push(backend.emitter.staticFunctionAccess(element));
|
| - push(new js.Call(pop(), arguments), node);
|
| + push(new js.Call(pop(), arguments,
|
| + sourceInformation: node.sourceInformation));
|
| }
|
|
|
| }
|
| @@ -1694,12 +1718,15 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| js.Name fieldName =
|
| backend.namer.instanceFieldPropertyName(superMethod);
|
| use(node.inputs[0]);
|
| - js.PropertyAccess access = new js.PropertyAccess(pop(), fieldName);
|
| + js.PropertyAccess access =
|
| + new js.PropertyAccess(pop(), fieldName)
|
| + .withSourceInformation(node.sourceInformation);
|
| if (node.isSetter) {
|
| use(node.value);
|
| - push(new js.Assignment(access, pop()), node);
|
| + push(new js.Assignment(access, pop())
|
| + .withSourceInformation(node.sourceInformation));
|
| } else {
|
| - push(access, node);
|
| + push(access);
|
| }
|
| } else {
|
| Selector selector = node.selector;
|
| @@ -1725,15 +1752,15 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| push(js.js('#.#.call(#)',
|
| [backend.emitter.prototypeAccess(superClass,
|
| hasBeenInstantiated: true),
|
| - methodName, visitArguments(node.inputs, start: 0)]),
|
| - node);
|
| + methodName, visitArguments(node.inputs, start: 0)])
|
| + .withSourceInformation(node.sourceInformation));
|
| } else {
|
| use(node.receiver);
|
| push(
|
| js.js('#.#(#)', [
|
| pop(), backend.namer.aliasedSuperMemberPropertyName(superMethod),
|
| - visitArguments(node.inputs, start: 1)]), // Skip receiver argument.
|
| - node);
|
| + visitArguments(node.inputs, start: 1)]) // Skip receiver argument.
|
| + .withSourceInformation(node.sourceInformation));
|
| }
|
| }
|
| }
|
| @@ -1745,15 +1772,18 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| // We access a JavaScript member we know all objects besides
|
| // null and undefined have: V8 does not like accessing a member
|
| // that does not exist.
|
| - push(new js.PropertyAccess.field(pop(), 'toString'), node);
|
| + push(new js.PropertyAccess.field(pop(), 'toString')
|
| + .withSourceInformation(node.sourceInformation));
|
| } else if (element == backend.jsIndexableLength) {
|
| // We're accessing a native JavaScript property called 'length'
|
| // on a JS String or a JS array. Therefore, the name of that
|
| // property should not be mangled.
|
| - push(new js.PropertyAccess.field(pop(), 'length'), node);
|
| + push(new js.PropertyAccess.field(pop(), 'length')
|
| + .withSourceInformation(node.sourceInformation));
|
| } else {
|
| js.Name name = backend.namer.instanceFieldPropertyName(element);
|
| - push(new js.PropertyAccess(pop(), name), node);
|
| + push(new js.PropertyAccess(pop(), name)
|
| + .withSourceInformation(node.sourceInformation));
|
| registry.registerFieldGetter(element);
|
| }
|
| }
|
| @@ -1765,8 +1795,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| use(node.receiver);
|
| js.Expression receiver = pop();
|
| use(node.value);
|
| - push(new js.Assignment(new js.PropertyAccess(receiver, name), pop()),
|
| - node);
|
| + push(new js.Assignment(new js.PropertyAccess(receiver, name), pop())
|
| + .withSourceInformation(node.sourceInformation));
|
| }
|
|
|
| visitReadModifyWrite(HReadModifyWrite node) {
|
| @@ -1776,12 +1806,15 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| use(node.receiver);
|
| js.Expression fieldReference = new js.PropertyAccess(pop(), name);
|
| if (node.isPreOp) {
|
| - push(new js.Prefix(node.jsOp, fieldReference), node);
|
| + push(new js.Prefix(node.jsOp, fieldReference)
|
| + .withSourceInformation(node.sourceInformation));
|
| } else if (node.isPostOp) {
|
| - push(new js.Postfix(node.jsOp, fieldReference), node);
|
| + push(new js.Postfix(node.jsOp, fieldReference)
|
| + .withSourceInformation(node.sourceInformation));
|
| } else {
|
| use(node.value);
|
| - push(new js.Assignment.compound(fieldReference, node.jsOp, pop()), node);
|
| + push(new js.Assignment.compound(fieldReference, node.jsOp, pop())
|
| + .withSourceInformation(node.sourceInformation));
|
| }
|
| }
|
|
|
| @@ -1791,7 +1824,9 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
|
|
| visitLocalSet(HLocalSet node) {
|
| use(node.value);
|
| - assignVariable(variableNames.getName(node.receiver), pop());
|
| + assignVariable(variableNames.getName(node.receiver),
|
| + pop(),
|
| + node.sourceInformation);
|
| }
|
|
|
| void registerForeignTypes(HForeign node) {
|
| @@ -1812,14 +1847,16 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| use(inputs[i]);
|
| interpolatedExpressions.add(pop());
|
| }
|
| - pushStatement(node.codeTemplate.instantiate(interpolatedExpressions));
|
| + pushStatement(node.codeTemplate.instantiate(interpolatedExpressions)
|
| + .withSourceInformation(node.sourceInformation));
|
| } else {
|
| List<js.Expression> interpolatedExpressions = <js.Expression>[];
|
| for (int i = 0; i < inputs.length; i++) {
|
| use(inputs[i]);
|
| interpolatedExpressions.add(pop());
|
| }
|
| - push(node.codeTemplate.instantiate(interpolatedExpressions));
|
| + push(node.codeTemplate.instantiate(interpolatedExpressions)
|
| + .withSourceInformation(node.sourceInformation));
|
| }
|
|
|
| // TODO(sra): Tell world.nativeEnqueuer about the types created here.
|
| @@ -1830,7 +1867,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| js.Expression jsClassReference =
|
| backend.emitter.constructorAccess(node.element);
|
| List<js.Expression> arguments = visitArguments(node.inputs, start: 0);
|
| - push(new js.New(jsClassReference, arguments), node);
|
| + push(new js.New(jsClassReference, arguments)
|
| + .withSourceInformation(node.sourceInformation));
|
| registerForeignTypes(node);
|
| // We also use ForeignNew to instantiate closure classes that belong to
|
| // function expressions. We have to register their use here, as otherwise
|
| @@ -1846,16 +1884,20 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| });
|
| }
|
|
|
| - js.Expression newLiteralBool(bool value) {
|
| + js.Expression newLiteralBool(bool value,
|
| + SourceInformation sourceInformation) {
|
| if (compiler.enableMinification) {
|
| // Use !0 for true, !1 for false.
|
| - return new js.Prefix("!", new js.LiteralNumber(value ? "0" : "1"));
|
| + return new js.Prefix("!", new js.LiteralNumber(value ? "0" : "1"))
|
| + .withSourceInformation(sourceInformation);
|
| } else {
|
| - return new js.LiteralBool(value);
|
| + return new js.LiteralBool(value)
|
| + .withSourceInformation(sourceInformation);
|
| }
|
| }
|
|
|
| - void generateConstant(ConstantValue constant) {
|
| + void generateConstant(ConstantValue constant,
|
| + SourceInformation sourceInformation) {
|
| if (constant.isFunction) {
|
| FunctionConstantValue function = constant;
|
| registry.registerStaticUse(function.element);
|
| @@ -1869,12 +1911,13 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| registry.registerTypeConstant(element);
|
| }
|
| }
|
| - push(backend.emitter.constantReference(constant));
|
| + push(backend.emitter.constantReference(constant)
|
| + .withSourceInformation(sourceInformation));
|
| }
|
|
|
| visitConstant(HConstant node) {
|
| assert(isGenerateAtUseSite(node));
|
| - generateConstant(node.constant);
|
| + generateConstant(node.constant, node.sourceInformation);
|
|
|
| registry.registerCompileTimeConstant(node.constant);
|
| backend.constants.addCompileTimeConstantForEmission(node.constant);
|
| @@ -1882,8 +1925,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
|
|
| visitNot(HNot node) {
|
| assert(node.inputs.length == 1);
|
| - generateNot(node.inputs[0]);
|
| - attachLocationToLast(node);
|
| + generateNot(node.inputs[0], node.sourceInformation);
|
| }
|
|
|
| static String mapRelationalOperator(String op, bool inverse) {
|
| @@ -1900,7 +1942,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| return inverse ? inverseOperator[op] : op;
|
| }
|
|
|
| - void generateNot(HInstruction input) {
|
| + void generateNot(HInstruction input, SourceInformation sourceInformation) {
|
| bool canGenerateOptimizedComparison(HInstruction instruction) {
|
| if (instruction is !HRelational) return false;
|
|
|
| @@ -1921,29 +1963,31 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| if (isGenerateAtUseSite(input)) {
|
| handledBySpecialCase = true;
|
| if (input is HIs) {
|
| - emitIs(input, '!==');
|
| + emitIs(input, '!==', sourceInformation);
|
| } else if (input is HIsViaInterceptor) {
|
| - emitIsViaInterceptor(input, true);
|
| + emitIsViaInterceptor(input, sourceInformation, negative: true);
|
| } else if (input is HNot) {
|
| use(input.inputs[0]);
|
| } else if (input is HIdentity) {
|
| - emitIdentityComparison(input, true);
|
| + emitIdentityComparison(input, sourceInformation, inverse: true);
|
| } else if (input is HBoolify) {
|
| use(input.inputs[0]);
|
| - push(new js.Binary("!==", pop(), newLiteralBool(true)), input);
|
| + push(new js.Binary("!==", pop(),
|
| + newLiteralBool(true, input.sourceInformation))
|
| + .withSourceInformation(sourceInformation));
|
| } else if (canGenerateOptimizedComparison(input)) {
|
| HRelational relational = input;
|
| BinaryOperation operation =
|
| relational.operation(backend.constantSystem);
|
| String op = mapRelationalOperator(operation.name, true);
|
| - visitRelational(input, op);
|
| + handleInvokeBinary(input, op, sourceInformation);
|
| } else {
|
| handledBySpecialCase = false;
|
| }
|
| }
|
| if (!handledBySpecialCase) {
|
| use(input);
|
| - push(new js.Prefix("!", pop()));
|
| + push(new js.Prefix("!", pop()).withSourceInformation(sourceInformation));
|
| }
|
| }
|
|
|
| @@ -1974,7 +2018,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| } else if (node.inputs[1].isConstantBoolean()) {
|
| String operation = node.inputs[1].isConstantFalse() ? '&&' : '||';
|
| if (operation == '||') {
|
| - generateNot(input);
|
| + generateNot(input, input.sourceInformation);
|
| } else {
|
| use(input);
|
| }
|
| @@ -1995,10 +2039,12 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| assert(node.inputs.length == 1);
|
| HInstruction input = node.inputs[0];
|
| if (input.isConstantNull()) {
|
| - pushStatement(new js.Return(null), node);
|
| + pushStatement(new js.Return()
|
| + .withSourceInformation(node.sourceInformation));
|
| } else {
|
| use(node.inputs[0]);
|
| - pushStatement(new js.Return(pop()), node);
|
| + pushStatement(new js.Return(pop())
|
| + .withSourceInformation(node.sourceInformation));
|
| }
|
| }
|
|
|
| @@ -2009,20 +2055,24 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| visitThrow(HThrow node) {
|
| if (node.isRethrow) {
|
| use(node.inputs[0]);
|
| - pushStatement(new js.Throw(pop()), node);
|
| + pushStatement(new js.Throw(pop())
|
| + .withSourceInformation(node.sourceInformation));
|
| } else {
|
| - generateThrowWithHelper('wrapException', node.inputs[0]);
|
| + generateThrowWithHelper('wrapException', node.inputs[0],
|
| + sourceInformation: node.sourceInformation);
|
| }
|
| }
|
|
|
| visitAwait(HAwait node) {
|
| use(node.inputs[0]);
|
| - push(new js.Await(pop()), node);
|
| + push(new js.Await(pop())
|
| + .withSourceInformation(node.sourceInformation));
|
| }
|
|
|
| visitYield(HYield node) {
|
| use(node.inputs[0]);
|
| - pushStatement(new js.DartYield(pop(), node.hasStar), node);
|
| + pushStatement(new js.DartYield(pop(), node.hasStar)
|
| + .withSourceInformation(node.sourceInformation));
|
| }
|
|
|
| visitRangeConversion(HRangeConversion node) {
|
| @@ -2072,13 +2122,15 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| generateThrowWithHelper('ioore', [node.array, node.index]);
|
| currentContainer = oldContainer;
|
| thenBody = unwrapStatement(thenBody);
|
| - pushStatement(new js.If.noElse(underOver, thenBody), node);
|
| + pushStatement(new js.If.noElse(underOver, thenBody)
|
| + .withSourceInformation(node.sourceInformation));
|
| } else {
|
| generateThrowWithHelper('ioore', [node.array, node.index]);
|
| }
|
| }
|
|
|
| - void generateThrowWithHelper(String helperName, argument) {
|
| + void generateThrowWithHelper(String helperName, argument,
|
| + {SourceInformation sourceInformation}) {
|
| Element helper = backend.findHelper(helperName);
|
| registry.registerStaticUse(helper);
|
| js.Expression jsHelper = backend.emitter.staticFunctionAccess(helper);
|
| @@ -2095,22 +2147,25 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| use(argument);
|
| arguments.add(pop());
|
| }
|
| - js.Call value = new js.Call(jsHelper, arguments.toList(growable: false));
|
| - value = attachLocation(value, location);
|
| + js.Call value = new js.Call(jsHelper, arguments.toList(growable: false),
|
| + sourceInformation: sourceInformation);
|
| // BUG(4906): Using throw/return here adds to the size of the generated code
|
| // but it has the advantage of explicitly telling the JS engine that
|
| // this code path will terminate abruptly. Needs more work.
|
| if (helperName == 'wrapException') {
|
| - pushStatement(new js.Throw(value));
|
| + pushStatement(new js.Throw(value)
|
| + .withSourceInformation(sourceInformation));
|
| } else {
|
| Element element = work.element;
|
| if (element is FunctionElement && element.asyncMarker.isYielding) {
|
| // `return <expr>;` is illegal in a sync* or async* function.
|
| // To have the the async-translator working, we avoid introducing
|
| // `return` nodes.
|
| - pushStatement(new js.ExpressionStatement(value));
|
| + pushStatement(new js.ExpressionStatement(value)
|
| + .withSourceInformation(sourceInformation));
|
| } else {
|
| - pushStatement(new js.Return(value));
|
| + pushStatement(new js.Return(value)
|
| + .withSourceInformation(sourceInformation));
|
| }
|
| }
|
| }
|
| @@ -2123,9 +2178,9 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| registry.registerStaticUse(helper);
|
|
|
| js.Expression jsHelper = backend.emitter.staticFunctionAccess(helper);
|
| - js.Call value = new js.Call(jsHelper, [pop()]);
|
| - value = attachLocation(value, argument);
|
| - push(value, node);
|
| + js.Call value = new js.Call(jsHelper, [pop()])
|
| + .withSourceInformation(node.sourceInformation);
|
| + push(value);
|
| }
|
|
|
| void visitSwitch(HSwitch node) {
|
| @@ -2136,10 +2191,12 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| Element element = node.element;
|
| assert(element.isFunction || element.isField);
|
| if (element.isFunction) {
|
| - push(backend.emitter.isolateStaticClosureAccess(element));
|
| + push(backend.emitter.isolateStaticClosureAccess(element)
|
| + .withSourceInformation(node.sourceInformation));
|
| registry.registerGetOfStaticFunction(element);
|
| } else {
|
| - push(backend.emitter.staticFieldAccess(element));
|
| + push(backend.emitter.staticFieldAccess(element)
|
| + .withSourceInformation(node.sourceInformation));
|
| }
|
| registry.registerStaticUse(element);
|
| }
|
| @@ -2149,22 +2206,25 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| registry.registerStaticUse(element);
|
| js.Expression lazyGetter =
|
| backend.emitter.isolateLazyInitializerAccess(element);
|
| - js.Call call = new js.Call(lazyGetter, <js.Expression>[]);
|
| - push(call, node);
|
| + js.Call call = new js.Call(lazyGetter, <js.Expression>[],
|
| + sourceInformation: node.sourceInformation);
|
| + push(call);
|
| }
|
|
|
| void visitStaticStore(HStaticStore node) {
|
| registry.registerStaticUse(node.element);
|
| js.Node variable = backend.emitter.staticFieldAccess(node.element);
|
| use(node.inputs[0]);
|
| - push(new js.Assignment(variable, pop()), node);
|
| + push(new js.Assignment(variable, pop())
|
| + .withSourceInformation(node.sourceInformation));
|
| }
|
|
|
| void visitStringConcat(HStringConcat node) {
|
| use(node.left);
|
| js.Expression jsLeft = pop();
|
| use(node.right);
|
| - push(new js.Binary('+', jsLeft, pop()), node);
|
| + push(new js.Binary('+', jsLeft, pop())
|
| + .withSourceInformation(node.sourceInformation));
|
| }
|
|
|
| void visitStringify(HStringify node) {
|
| @@ -2181,7 +2241,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| // The context is already <string> + value.
|
| } else {
|
| // Force an empty string for the first operand.
|
| - push(new js.Binary('+', js.string(""), pop()), node);
|
| + push(new js.Binary('+', js.string(""), pop())
|
| + .withSourceInformation(node.sourceInformation));
|
| }
|
| } else {
|
| Element convertToString = backend.getStringInterpolationHelper();
|
| @@ -2189,7 +2250,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| js.Expression jsHelper =
|
| backend.emitter.staticFunctionAccess(convertToString);
|
| use(input);
|
| - push(new js.Call(jsHelper, <js.Expression>[pop()]), node);
|
| + push(new js.Call(jsHelper, <js.Expression>[pop()],
|
| + sourceInformation: node.sourceInformation));
|
| }
|
| }
|
|
|
| @@ -2203,14 +2265,16 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| use(input);
|
| return pop();
|
| }).toList();
|
| - push(new js.ArrayInitializer(elements), node);
|
| + push(new js.ArrayInitializer(elements)
|
| + .withSourceInformation(node.sourceInformation));
|
| }
|
|
|
| void visitIndex(HIndex node) {
|
| use(node.receiver);
|
| js.Expression receiver = pop();
|
| use(node.index);
|
| - push(new js.PropertyAccess(receiver, pop()), node);
|
| + push(new js.PropertyAccess(receiver, pop())
|
| + .withSourceInformation(node.sourceInformation));
|
| }
|
|
|
| void visitIndexAssign(HIndexAssign node) {
|
| @@ -2219,8 +2283,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| use(node.index);
|
| js.Expression index = pop();
|
| use(node.value);
|
| - push(new js.Assignment(new js.PropertyAccess(receiver, index), pop()),
|
| - node);
|
| + push(new js.Assignment(new js.PropertyAccess(receiver, index), pop())
|
| + .withSourceInformation(node.sourceInformation));
|
| }
|
|
|
| void checkInt(HInstruction input, String cmp) {
|
| @@ -2231,47 +2295,62 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| push(new js.Binary(cmp, left, or0));
|
| }
|
|
|
| - void checkBigInt(HInstruction input, String cmp) {
|
| + void checkBigInt(HInstruction input, String cmp,
|
| + SourceInformation sourceInformation) {
|
| use(input);
|
| js.Expression left = pop();
|
| use(input);
|
| js.Expression right = pop();
|
| // TODO(4984): Deal with infinity and -0.0.
|
| - push(js.js('Math.floor(#) $cmp #', <js.Expression>[left, right]));
|
| + push(js.js('Math.floor(#) $cmp #', <js.Expression>[left, right])
|
| + .withSourceInformation(sourceInformation));
|
| }
|
|
|
| - void checkTypeOf(HInstruction input, String cmp, String typeName) {
|
| + void checkTypeOf(HInstruction input, String cmp, String typeName,
|
| + SourceInformation sourceInformation) {
|
| use(input);
|
| js.Expression typeOf = new js.Prefix("typeof", pop());
|
| push(new js.Binary(cmp, typeOf, js.string(typeName)));
|
| }
|
|
|
| - void checkNum(HInstruction input, String cmp)
|
| - => checkTypeOf(input, cmp, 'number');
|
| + void checkNum(HInstruction input, String cmp,
|
| + SourceInformation sourceInformation) {
|
| + return checkTypeOf(input, cmp, 'number', sourceInformation);
|
| + }
|
|
|
| - void checkDouble(HInstruction input, String cmp) => checkNum(input, cmp);
|
| + void checkDouble(HInstruction input, String cmp,
|
| + SourceInformation sourceInformation) {
|
| + return checkNum(input, cmp, sourceInformation);
|
| + }
|
|
|
| - void checkString(HInstruction input, String cmp)
|
| - => checkTypeOf(input, cmp, 'string');
|
| + void checkString(HInstruction input, String cmp,
|
| + SourceInformation sourceInformation) {
|
| + return checkTypeOf(input, cmp, 'string', sourceInformation);
|
| + }
|
|
|
| - void checkBool(HInstruction input, String cmp)
|
| - => checkTypeOf(input, cmp, 'boolean');
|
| + void checkBool(HInstruction input, String cmp,
|
| + SourceInformation sourceInformation) {
|
| + return checkTypeOf(input, cmp, 'boolean', sourceInformation);
|
| + }
|
|
|
| - void checkObject(HInstruction input, String cmp) {
|
| + void checkObject(HInstruction input, String cmp,
|
| + SourceInformation sourceInformation) {
|
| assert(NullConstantValue.JsNull == 'null');
|
| if (cmp == "===") {
|
| - checkTypeOf(input, '===', 'object');
|
| + checkTypeOf(input, '===', 'object', sourceInformation);
|
| js.Expression left = pop();
|
| use(input);
|
| js.Expression notNull = new js.Binary("!==", pop(), new js.LiteralNull());
|
| - push(new js.Binary("&&", left, notNull));
|
| + push(new js.Binary("&&", left, notNull)
|
| + .withSourceInformation(sourceInformation));
|
| } else {
|
| assert(cmp == "!==");
|
| - checkTypeOf(input, '!==', 'object');
|
| + checkTypeOf(input, '!==', 'object', sourceInformation);
|
| js.Expression left = pop();
|
| use(input);
|
| js.Expression eqNull = new js.Binary("===", pop(), new js.LiteralNull());
|
| - push(new js.Binary("||", left, eqNull));
|
| + push(new js.Binary("||", left, eqNull)
|
| + .withSourceInformation(sourceInformation));
|
| }
|
| }
|
|
|
| @@ -2322,7 +2401,9 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| }
|
|
|
| void checkType(HInstruction input, HInstruction interceptor,
|
| - DartType type, {bool negative: false}) {
|
| + DartType type,
|
| + SourceInformation sourceInformation,
|
| + {bool negative: false}) {
|
| Element element = type.element;
|
| if (element == backend.jsArrayClass) {
|
| checkArray(input, negative ? '!==': '===');
|
| @@ -2357,73 +2438,92 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| return;
|
| }
|
| if (interceptor != null) {
|
| - checkTypeViaProperty(interceptor, type, negative);
|
| + checkTypeViaProperty(interceptor, type, sourceInformation,
|
| + negative: negative);
|
| } else {
|
| - checkTypeViaProperty(input, type, negative);
|
| + checkTypeViaProperty(input, type, sourceInformation, negative: negative);
|
| }
|
| }
|
|
|
| - void checkTypeViaProperty(HInstruction input, DartType type, bool negative) {
|
| + void checkTypeViaProperty(HInstruction input, DartType type,
|
| + SourceInformation sourceInformation,
|
| + {bool negative: false}) {
|
| registry.registerIsCheck(type);
|
|
|
| use(input);
|
|
|
| js.PropertyAccess field =
|
| - new js.PropertyAccess(pop(), backend.namer.operatorIsType(type));
|
| + new js.PropertyAccess(pop(), backend.namer.operatorIsType(type))
|
| + .withSourceInformation(sourceInformation);
|
| // We always negate at least once so that the result is boolified.
|
| - push(new js.Prefix('!', field));
|
| + push(new js.Prefix('!', field)
|
| + .withSourceInformation(sourceInformation));
|
| // If the result is not negated, put another '!' in front.
|
| - if (!negative) push(new js.Prefix('!', pop()));
|
| + if (!negative) {
|
| + push(new js.Prefix('!', pop())
|
| + .withSourceInformation(sourceInformation));
|
| + }
|
| }
|
|
|
| void checkTypeViaInstanceof(
|
| - HInstruction input, DartType type, bool negative) {
|
| + HInstruction input, DartType type,
|
| + SourceInformation sourceInformation,
|
| + {bool negative: false}) {
|
| registry.registerIsCheck(type);
|
|
|
| use(input);
|
|
|
| js.Expression jsClassReference =
|
| backend.emitter.constructorAccess(type.element);
|
| - push(js.js('# instanceof #', [pop(), jsClassReference]));
|
| - if (negative) push(new js.Prefix('!', pop()));
|
| + push(js.js('# instanceof #', [pop(), jsClassReference])
|
| + .withSourceInformation(sourceInformation));
|
| + if (negative) {
|
| + push(new js.Prefix('!', pop())
|
| + .withSourceInformation(sourceInformation));
|
| + }
|
| registry.registerInstantiatedType(type);
|
| }
|
|
|
| void handleNumberOrStringSupertypeCheck(HInstruction input,
|
| HInstruction interceptor,
|
| DartType type,
|
| - { bool negative: false }) {
|
| - assert(!identical(type.element, compiler.listClass)
|
| - && !Elements.isListSupertype(type.element, compiler)
|
| - && !Elements.isStringOnlySupertype(type.element, compiler));
|
| + SourceInformation sourceInformation,
|
| + {bool negative: false}) {
|
| + assert(!identical(type.element, compiler.listClass) &&
|
| + !Elements.isListSupertype(type.element, compiler) &&
|
| + !Elements.isStringOnlySupertype(type.element, compiler));
|
| String relation = negative ? '!==' : '===';
|
| - checkNum(input, relation);
|
| + checkNum(input, relation, sourceInformation);
|
| js.Expression numberTest = pop();
|
| - checkString(input, relation);
|
| + checkString(input, relation, sourceInformation);
|
| js.Expression stringTest = pop();
|
| - checkObject(input, relation);
|
| + checkObject(input, relation, sourceInformation);
|
| js.Expression objectTest = pop();
|
| - checkType(input, interceptor, type, negative: negative);
|
| + checkType(input, interceptor, type, sourceInformation, negative: negative);
|
| String combiner = negative ? '&&' : '||';
|
| String combiner2 = negative ? '||' : '&&';
|
| push(new js.Binary(combiner,
|
| - new js.Binary(combiner, numberTest, stringTest),
|
| - new js.Binary(combiner2, objectTest, pop())));
|
| + new js.Binary(combiner, numberTest, stringTest)
|
| + .withSourceInformation(sourceInformation),
|
| + new js.Binary(combiner2, objectTest, pop())
|
| + .withSourceInformation(sourceInformation))
|
| + .withSourceInformation(sourceInformation));
|
| }
|
|
|
| void handleStringSupertypeCheck(HInstruction input,
|
| HInstruction interceptor,
|
| DartType type,
|
| - { bool negative: false }) {
|
| + SourceInformation sourceInformation,
|
| + {bool negative: false}) {
|
| assert(!identical(type.element, compiler.listClass)
|
| && !Elements.isListSupertype(type.element, compiler)
|
| && !Elements.isNumberOrStringSupertype(type.element, compiler));
|
| String relation = negative ? '!==' : '===';
|
| - checkString(input, relation);
|
| + checkString(input, relation, sourceInformation);
|
| js.Expression stringTest = pop();
|
| - checkObject(input, relation);
|
| + checkObject(input, relation, sourceInformation);
|
| js.Expression objectTest = pop();
|
| - checkType(input, interceptor, type, negative: negative);
|
| + checkType(input, interceptor, type, sourceInformation, negative: negative);
|
| String combiner = negative ? '||' : '&&';
|
| push(new js.Binary(negative ? '&&' : '||',
|
| stringTest,
|
| @@ -2433,31 +2533,33 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| void handleListOrSupertypeCheck(HInstruction input,
|
| HInstruction interceptor,
|
| DartType type,
|
| + SourceInformation sourceInformation,
|
| { bool negative: false }) {
|
| assert(!identical(type.element, compiler.stringClass)
|
| && !Elements.isStringOnlySupertype(type.element, compiler)
|
| && !Elements.isNumberOrStringSupertype(type.element, compiler));
|
| String relation = negative ? '!==' : '===';
|
| - checkObject(input, relation);
|
| + checkObject(input, relation, sourceInformation);
|
| js.Expression objectTest = pop();
|
| checkArray(input, relation);
|
| js.Expression arrayTest = pop();
|
| - checkType(input, interceptor, type, negative: negative);
|
| + checkType(input, interceptor, type, sourceInformation, negative: negative);
|
| String combiner = negative ? '&&' : '||';
|
| push(new js.Binary(negative ? '||' : '&&',
|
| objectTest,
|
| - new js.Binary(combiner, arrayTest, pop())));
|
| + new js.Binary(combiner, arrayTest, pop()))
|
| + .withSourceInformation(sourceInformation));
|
| }
|
|
|
| void visitIs(HIs node) {
|
| - emitIs(node, "===");
|
| + emitIs(node, "===", node.sourceInformation);
|
| }
|
|
|
| void visitIsViaInterceptor(HIsViaInterceptor node) {
|
| - emitIsViaInterceptor(node, false);
|
| + emitIsViaInterceptor(node, node.sourceInformation, negative: false);
|
| }
|
|
|
| - void emitIs(HIs node, String relation) {
|
| + void emitIs(HIs node, String relation, SourceInformation sourceInformation) {
|
| DartType type = node.typeExpression;
|
| registry.registerIsCheck(type);
|
| HInstruction input = node.expression;
|
| @@ -2484,64 +2586,73 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| } else if (identical(element, objectClass) || type.treatAsDynamic) {
|
| // The constant folder also does this optimization, but we make
|
| // it safe by assuming it may have not run.
|
| - push(newLiteralBool(!negative), node);
|
| + push(newLiteralBool(!negative, sourceInformation));
|
| } else if (element == compiler.stringClass) {
|
| - checkString(input, relation);
|
| - attachLocationToLast(node);
|
| + checkString(input, relation, sourceInformation);
|
| } else if (element == compiler.doubleClass) {
|
| - checkDouble(input, relation);
|
| - attachLocationToLast(node);
|
| + checkDouble(input, relation, sourceInformation);
|
| } else if (element == compiler.numClass) {
|
| - checkNum(input, relation);
|
| - attachLocationToLast(node);
|
| + checkNum(input, relation, sourceInformation);
|
| } else if (element == compiler.boolClass) {
|
| - checkBool(input, relation);
|
| - attachLocationToLast(node);
|
| + checkBool(input, relation, sourceInformation);
|
| } else if (element == compiler.intClass) {
|
| // The is check in the code tells us that it might not be an
|
| // int. So we do a typeof first to avoid possible
|
| // deoptimizations on the JS engine due to the Math.floor check.
|
| - checkNum(input, relation);
|
| + checkNum(input, relation, sourceInformation);
|
| js.Expression numTest = pop();
|
| - checkBigInt(input, relation);
|
| - push(new js.Binary(negative ? '||' : '&&', numTest, pop()), node);
|
| + checkBigInt(input, relation, sourceInformation);
|
| + push(new js.Binary(negative ? '||' : '&&', numTest, pop())
|
| + .withSourceInformation(sourceInformation));
|
| } else if (node.useInstanceOf) {
|
| assert(interceptor == null);
|
| - checkTypeViaInstanceof(input, type, negative);
|
| - attachLocationToLast(node);
|
| + checkTypeViaInstanceof(input, type,
|
| + sourceInformation,
|
| + negative: negative);
|
| } else if (Elements.isNumberOrStringSupertype(element, compiler)) {
|
| handleNumberOrStringSupertypeCheck(
|
| - input, interceptor, type, negative: negative);
|
| - attachLocationToLast(node);
|
| + input, interceptor, type,
|
| + sourceInformation,
|
| + negative: negative);
|
| } else if (Elements.isStringOnlySupertype(element, compiler)) {
|
| handleStringSupertypeCheck(
|
| - input, interceptor, type, negative: negative);
|
| - attachLocationToLast(node);
|
| - } else if (identical(element, compiler.listClass)
|
| - || Elements.isListSupertype(element, compiler)) {
|
| + input, interceptor, type,
|
| + sourceInformation,
|
| + negative: negative);
|
| + } else if (identical(element, compiler.listClass) ||
|
| + Elements.isListSupertype(element, compiler)) {
|
| handleListOrSupertypeCheck(
|
| - input, interceptor, type, negative: negative);
|
| - attachLocationToLast(node);
|
| + input, interceptor, type,
|
| + sourceInformation,
|
| + negative: negative);
|
| } else if (type.isFunctionType) {
|
| - checkType(input, interceptor, type, negative: negative);
|
| - attachLocationToLast(node);
|
| + checkType(input, interceptor, type,
|
| + sourceInformation,
|
| + negative: negative);
|
| } else if ((input.canBePrimitive(compiler)
|
| && !input.canBePrimitiveArray(compiler))
|
| || input.canBeNull()) {
|
| - checkObject(input, relation);
|
| + checkObject(input, relation, node.sourceInformation);
|
| js.Expression objectTest = pop();
|
| - checkType(input, interceptor, type, negative: negative);
|
| - push(new js.Binary(negative ? '||' : '&&', objectTest, pop()), node);
|
| + checkType(input, interceptor, type,
|
| + sourceInformation,
|
| + negative: negative);
|
| + push(new js.Binary(negative ? '||' : '&&', objectTest, pop())
|
| + .withSourceInformation(sourceInformation));
|
| } else {
|
| - checkType(input, interceptor, type, negative: negative);
|
| - attachLocationToLast(node);
|
| + checkType(input, interceptor, type,
|
| + sourceInformation,
|
| + negative: negative);
|
| }
|
| }
|
| }
|
|
|
| - void emitIsViaInterceptor(HIsViaInterceptor node, bool negative) {
|
| - checkTypeViaProperty(node.interceptor, node.typeExpression, negative);
|
| - attachLocationToLast(node);
|
| + void emitIsViaInterceptor(HIsViaInterceptor node,
|
| + SourceInformation sourceInformation,
|
| + {bool negative: false}) {
|
| + checkTypeViaProperty(node.interceptor, node.typeExpression,
|
| + sourceInformation,
|
| + negative: negative);
|
| }
|
|
|
| js.Expression generateReceiverOrArgumentTypeTest(
|
| @@ -2561,22 +2672,23 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
|
|
| if (turnIntoNullCheck) {
|
| use(input);
|
| - return new js.Binary("==", pop(), new js.LiteralNull());
|
| + return new js.Binary("==", pop(), new js.LiteralNull())
|
| + .withSourceInformation(input.sourceInformation);
|
| } else if (isIntCheck && !turnIntoNumCheck) {
|
| // input is !int
|
| - checkBigInt(input, '!==');
|
| + checkBigInt(input, '!==', input.sourceInformation);
|
| return pop();
|
| } else if (turnIntoNumCheck || checkedType.containsOnlyNum(classWorld)) {
|
| // input is !num
|
| - checkNum(input, '!==');
|
| + checkNum(input, '!==', input.sourceInformation);
|
| return pop();
|
| } else if (checkedType.containsOnlyBool(classWorld)) {
|
| // input is !bool
|
| - checkBool(input, '!==');
|
| + checkBool(input, '!==', input.sourceInformation);
|
| return pop();
|
| } else if (checkedType.containsOnlyString(classWorld)) {
|
| // input is !string
|
| - checkString(input, '!==');
|
| + checkString(input, '!==', input.sourceInformation);
|
| return pop();
|
| }
|
| compiler.internalError(input, 'Unexpected check.');
|
| @@ -2607,7 +2719,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| }
|
| currentContainer = oldContainer;
|
| body = unwrapStatement(body);
|
| - pushStatement(new js.If.noElse(test, body), node);
|
| + pushStatement(new js.If.noElse(test, body)
|
| + .withSourceInformation(node.sourceInformation));
|
| return;
|
| }
|
|
|
|
|