| 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 f641db6f6dac73e2b1f41bcf0d29c5e1f6621fc9..2e9291341ad7abcdbbf2bf7ac9327ea42e0f6201 100644
|
| --- a/pkg/compiler/lib/src/ssa/codegen.dart
|
| +++ b/pkg/compiler/lib/src/ssa/codegen.dart
|
| @@ -6,26 +6,22 @@ import 'dart:math' as math;
|
| import '../common.dart';
|
| import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
|
| import '../common/tasks.dart' show CompilerTask;
|
| -import '../compiler.dart' show Compiler;
|
| import '../constants/constant_system.dart';
|
| import '../constants/values.dart';
|
| import '../common_elements.dart' show CommonElements;
|
| import '../elements/elements.dart'
|
| - show
|
| - AsyncMarker,
|
| - JumpTarget,
|
| - LabelDefinition,
|
| - MethodElement,
|
| - Name,
|
| - ResolvedAst;
|
| + show AsyncMarker, JumpTarget, LabelDefinition, MethodElement, ResolvedAst;
|
| import '../elements/entities.dart';
|
| import '../elements/types.dart';
|
| import '../io/source_information.dart';
|
| import '../js/js.dart' as js;
|
| import '../js_backend/backend_helpers.dart' show BackendHelpers;
|
| +import '../js_backend/interceptor_data.dart';
|
| import '../js_backend/js_backend.dart';
|
| -import '../js_emitter/js_emitter.dart' show NativeEmitter;
|
| +import '../js_backend/native_data.dart';
|
| +import '../js_emitter/code_emitter_task.dart';
|
| import '../native/native.dart' as native;
|
| +import '../options.dart';
|
| import '../types/types.dart';
|
| import '../universe/call_structure.dart' show CallStructure;
|
| import '../universe/selector.dart' show Selector;
|
| @@ -38,16 +34,13 @@ import 'variable_allocator.dart';
|
|
|
| class SsaCodeGeneratorTask extends CompilerTask {
|
| final JavaScriptBackend backend;
|
| - final Compiler compiler;
|
| final SourceInformationStrategy sourceInformationFactory;
|
|
|
| SsaCodeGeneratorTask(JavaScriptBackend backend, this.sourceInformationFactory)
|
| : this.backend = backend,
|
| - this.compiler = backend.compiler,
|
| super(backend.compiler.measurer);
|
|
|
| String get name => 'SSA code generator';
|
| - NativeEmitter get nativeEmitter => backend.emitter.nativeEmitter;
|
|
|
| js.Fun buildJavaScriptFunction(
|
| ResolvedAst resolvedAst, List<js.Parameter> parameters, js.Block body) {
|
| @@ -82,8 +75,21 @@ class SsaCodeGeneratorTask extends CompilerTask {
|
| SourceInformation sourceInformation = sourceInformationFactory
|
| .createBuilderForContext(work.resolvedAst)
|
| .buildDeclaration(work.resolvedAst);
|
| - SsaCodeGenerator codegen =
|
| - new SsaCodeGenerator(backend, closedWorld, work);
|
| + SsaCodeGenerator codegen = new SsaCodeGenerator(
|
| + backend.compiler.options,
|
| + backend.emitter,
|
| + backend.nativeCodegenEnqueuer,
|
| + backend.helpers,
|
| + backend.checkedModeHelpers,
|
| + backend.nativeData,
|
| + backend.interceptorData,
|
| + backend.oneShotInterceptorData,
|
| + backend.rtiSubstitutions,
|
| + backend.rtiEncoder,
|
| + backend.namer,
|
| + backend.superMemberData,
|
| + closedWorld,
|
| + work);
|
| codegen.visitGraph(graph);
|
| return new js.Fun(codegen.parameters, codegen.body)
|
| .withSourceInformation(sourceInformation);
|
| @@ -97,8 +103,21 @@ class SsaCodeGeneratorTask extends CompilerTask {
|
| if (element.asyncMarker != AsyncMarker.SYNC) {
|
| work.registry.registerAsyncMarker(element);
|
| }
|
| - SsaCodeGenerator codegen =
|
| - new SsaCodeGenerator(backend, closedWorld, work);
|
| + SsaCodeGenerator codegen = new SsaCodeGenerator(
|
| + backend.compiler.options,
|
| + backend.emitter,
|
| + backend.nativeCodegenEnqueuer,
|
| + backend.helpers,
|
| + backend.checkedModeHelpers,
|
| + backend.nativeData,
|
| + backend.interceptorData,
|
| + backend.oneShotInterceptorData,
|
| + backend.rtiSubstitutions,
|
| + backend.rtiEncoder,
|
| + backend.namer,
|
| + backend.superMemberData,
|
| + closedWorld,
|
| + work);
|
| codegen.visitGraph(graph);
|
| backend.tracer.traceGraph("codegen", graph);
|
| return buildJavaScriptFunction(
|
| @@ -132,9 +151,20 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| */
|
| bool isGeneratingExpression = false;
|
|
|
| - final JavaScriptBackend backend;
|
| - final ClosedWorld closedWorld;
|
| - final CodegenWorkItem work;
|
| + final CompilerOptions _options;
|
| + final CodeEmitterTask _emitter;
|
| + final native.NativeCodegenEnqueuer _nativeEnqueuer;
|
| + final BackendHelpers _helpers;
|
| + final CheckedModeHelpers _checkedModeHelpers;
|
| + final NativeData _nativeData;
|
| + final InterceptorData _interceptorData;
|
| + final OneShotInterceptorData _oneShotInterceptorData;
|
| + final RuntimeTypesSubstitutions _rtiSubstitutions;
|
| + final RuntimeTypesEncoder _rtiEncoder;
|
| + final Namer _namer;
|
| + final SuperMemberData _superMemberData;
|
| + final ClosedWorld _closedWorld;
|
| + final CodegenWorkItem _work;
|
|
|
| final Set<HInstruction> generateAtUseSite;
|
| final Set<HInstruction> controlFlowOperators;
|
| @@ -176,10 +206,23 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| // if branches.
|
| SubGraph subGraph;
|
|
|
| - SsaCodeGenerator(this.backend, this.closedWorld, CodegenWorkItem work,
|
| + SsaCodeGenerator(
|
| + this._options,
|
| + this._emitter,
|
| + this._nativeEnqueuer,
|
| + this._helpers,
|
| + this._checkedModeHelpers,
|
| + this._nativeData,
|
| + this._interceptorData,
|
| + this._oneShotInterceptorData,
|
| + this._rtiSubstitutions,
|
| + this._rtiEncoder,
|
| + this._namer,
|
| + this._superMemberData,
|
| + this._closedWorld,
|
| + this._work,
|
| {SourceInformation sourceInformation})
|
| - : this.work = work,
|
| - declaredLocals = new Set<String>(),
|
| + : declaredLocals = new Set<String>(),
|
| collectedVariableDeclarations = new Set<String>(),
|
| currentContainer = new js.Block.empty(),
|
| parameters = <js.Parameter>[],
|
| @@ -190,21 +233,11 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| breakAction = new Map<Entity, EntityAction>(),
|
| continueAction = new Map<Entity, EntityAction>();
|
|
|
| - Compiler get compiler => backend.compiler;
|
| -
|
| - NativeEmitter get nativeEmitter => backend.emitter.nativeEmitter;
|
| -
|
| - CodegenRegistry get registry => work.registry;
|
| -
|
| - BackendHelpers get helpers => backend.helpers;
|
| -
|
| - native.NativeCodegenEnqueuer get nativeEnqueuer {
|
| - return backend.nativeCodegenEnqueuer;
|
| - }
|
| + CodegenRegistry get _registry => _work.registry;
|
|
|
| - DiagnosticReporter get reporter => compiler.reporter;
|
| + CommonElements get _commonElements => _closedWorld.commonElements;
|
|
|
| - CommonElements get commonElements => closedWorld.commonElements;
|
| + ConstantSystem get _constantSystem => _closedWorld.constantSystem;
|
|
|
| bool isGenerateAtUseSite(HInstruction instruction) {
|
| return generateAtUseSite.contains(instruction);
|
| @@ -275,7 +308,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| }
|
|
|
| bool requiresUintConversion(HInstruction instruction) {
|
| - if (instruction.isUInt31(closedWorld)) return false;
|
| + if (instruction.isUInt31(_closedWorld)) return false;
|
| if (bitWidth(instruction) <= 31) return false;
|
| // If the result of a bit-operation is only used by other bit
|
| // operations, we do not have to convert to an unsigned integer.
|
| @@ -318,11 +351,11 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| }
|
|
|
| void preGenerateMethod(HGraph graph) {
|
| - new SsaInstructionSelection(closedWorld, backend.interceptorData)
|
| + new SsaInstructionSelection(_closedWorld, _interceptorData)
|
| .visitGraph(graph);
|
| new SsaTypeKnownRemover().visitGraph(graph);
|
| - new SsaTrustedCheckRemover(compiler.options).visitGraph(graph);
|
| - new SsaInstructionMerger(generateAtUseSite, backend.superMemberData)
|
| + new SsaTrustedCheckRemover(_options).visitGraph(graph);
|
| + new SsaInstructionMerger(generateAtUseSite, _superMemberData)
|
| .visitGraph(graph);
|
| new SsaConditionMerger(generateAtUseSite, controlFlowOperators)
|
| .visitGraph(graph);
|
| @@ -330,7 +363,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| new SsaLiveIntervalBuilder(generateAtUseSite, controlFlowOperators);
|
| intervalBuilder.visitGraph(graph);
|
| SsaVariableAllocator allocator = new SsaVariableAllocator(
|
| - backend.namer,
|
| + _namer,
|
| intervalBuilder.liveInstructions,
|
| intervalBuilder.liveIntervals,
|
| generateAtUseSite);
|
| @@ -694,23 +727,22 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| }
|
|
|
| void continueAsBreak(LabelDefinition target) {
|
| - pushStatement(new js.Break(backend.namer.continueLabelName(target)));
|
| + pushStatement(new js.Break(_namer.continueLabelName(target)));
|
| }
|
|
|
| void implicitContinueAsBreak(JumpTarget target) {
|
| - pushStatement(
|
| - new js.Break(backend.namer.implicitContinueLabelName(target)));
|
| + pushStatement(new js.Break(_namer.implicitContinueLabelName(target)));
|
| }
|
|
|
| void implicitBreakWithLabel(JumpTarget target) {
|
| - pushStatement(new js.Break(backend.namer.implicitBreakLabelName(target)));
|
| + pushStatement(new js.Break(_namer.implicitBreakLabelName(target)));
|
| }
|
|
|
| js.Statement wrapIntoLabels(
|
| js.Statement result, List<LabelDefinition> labels) {
|
| for (LabelDefinition label in labels) {
|
| if (label.isTarget) {
|
| - String breakLabelString = backend.namer.breakLabelName(label);
|
| + String breakLabelString = _namer.breakLabelName(label);
|
| result = new js.LabeledStatement(breakLabelString, result);
|
| }
|
| }
|
| @@ -805,12 +837,12 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| if (info.catchBlock != null) {
|
| void register(ClassEntity classElement) {
|
| if (classElement != null) {
|
| - registry.registerInstantiatedClass(classElement);
|
| + _registry.registerInstantiatedClass(classElement);
|
| }
|
| }
|
|
|
| - register(helpers.jsPlainJavaScriptObjectClass);
|
| - register(helpers.jsUnknownJavaScriptObjectClass);
|
| + register(_helpers.jsPlainJavaScriptObjectClass);
|
| + register(_helpers.jsUnknownJavaScriptObjectClass);
|
|
|
| HLocalValue exception = info.catchVariable;
|
| String name = variableNames.getName(exception);
|
| @@ -1043,13 +1075,13 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| currentContainer = oldContainer;
|
| break;
|
| default:
|
| - reporter.internalError(condition.conditionExpression,
|
| + throw new SpannableAssertionFailure(condition.conditionExpression,
|
| 'Unexpected loop kind: ${info.kind}.');
|
| }
|
| js.Statement result = loop;
|
| if (info.kind == HLoopBlockInformation.SWITCH_CONTINUE_LOOP) {
|
| String continueLabelString =
|
| - backend.namer.implicitContinueLabelName(info.target);
|
| + _namer.implicitContinueLabelName(info.target);
|
| result = new js.LabeledStatement(continueLabelString, result);
|
| }
|
| pushStatement(wrapIntoLabels(result, info.labels));
|
| @@ -1072,7 +1104,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| if (labeledBlockInfo.isContinue) {
|
| for (LabelDefinition label in labeledBlockInfo.labels) {
|
| if (label.isContinueTarget) {
|
| - String labelName = backend.namer.continueLabelName(label);
|
| + String labelName = _namer.continueLabelName(label);
|
| result = new js.LabeledStatement(labelName, result);
|
| continueAction[label] = continueAsBreak;
|
| continueOverrides = continueOverrides.prepend(label);
|
| @@ -1082,14 +1114,14 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| // TODO(lrn): Consider recording whether the target is in fact
|
| // a target of an unlabeled continue, and not generate this if it isn't.
|
| JumpTarget target = labeledBlockInfo.target;
|
| - String labelName = backend.namer.implicitContinueLabelName(target);
|
| + String labelName = _namer.implicitContinueLabelName(target);
|
| result = new js.LabeledStatement(labelName, result);
|
| continueAction[target] = implicitContinueAsBreak;
|
| continueOverrides = continueOverrides.prepend(target);
|
| } else {
|
| for (LabelDefinition label in labeledBlockInfo.labels) {
|
| if (label.isBreakTarget) {
|
| - String labelName = backend.namer.breakLabelName(label);
|
| + String labelName = _namer.breakLabelName(label);
|
| result = new js.LabeledStatement(labelName, result);
|
| }
|
| }
|
| @@ -1099,7 +1131,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| // This is an extra block around a switch that is generated
|
| // as a nested if/else chain. We add an extra break target
|
| // so that case code can break.
|
| - String labelName = backend.namer.implicitBreakLabelName(target);
|
| + String labelName = _namer.implicitBreakLabelName(target);
|
| result = new js.LabeledStatement(labelName, result);
|
| breakAction[target] = implicitBreakWithLabel;
|
| }
|
| @@ -1132,12 +1164,12 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| js.Statement result = body;
|
| for (LabelDefinition label in info.labels) {
|
| if (label.isContinueTarget) {
|
| - String labelName = backend.namer.continueLabelName(label);
|
| + String labelName = _namer.continueLabelName(label);
|
| result = new js.LabeledStatement(labelName, result);
|
| continueAction[label] = continueAsBreak;
|
| }
|
| }
|
| - String labelName = backend.namer.implicitContinueLabelName(target);
|
| + String labelName = _namer.implicitContinueLabelName(target);
|
| result = new js.LabeledStatement(labelName, result);
|
| continueAction[info.target] = implicitContinueAsBreak;
|
| visitBodyIgnoreLabels(info);
|
| @@ -1396,11 +1428,11 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| visitShiftRight(HShiftRight node) => visitBitInvokeBinary(node, '>>>');
|
|
|
| visitTruncatingDivide(HTruncatingDivide node) {
|
| - assert(node.isUInt31(closedWorld));
|
| + assert(node.isUInt31(_closedWorld));
|
| // TODO(karlklose): Enable this assertion again when type propagation is
|
| // fixed. Issue 23555.
|
| // assert(node.left.isUInt32(compiler));
|
| - assert(node.right.isPositiveInteger(closedWorld));
|
| + assert(node.right.isPositiveInteger(_closedWorld));
|
| use(node.left);
|
| js.Expression jsLeft = pop();
|
| use(node.right);
|
| @@ -1444,10 +1476,12 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| // is responsible for visiting the successor.
|
| if (dominated.isEmpty) return;
|
| if (dominated.length > 2) {
|
| - reporter.internalError(node, 'dominated.length = ${dominated.length}');
|
| + throw new SpannableAssertionFailure(
|
| + node, 'dominated.length = ${dominated.length}');
|
| }
|
| if (dominated.length == 2 && block != currentGraph.entry) {
|
| - reporter.internalError(node, 'node.block != currentGraph.entry');
|
| + throw new SpannableAssertionFailure(
|
| + node, 'node.block != currentGraph.entry');
|
| }
|
| assert(dominated[0] == block.successors[0]);
|
| visitBasicBlock(dominated[0]);
|
| @@ -1482,16 +1516,15 @@ 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))
|
| + pushStatement(new js.Break(_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))
|
| - .withSourceInformation(node.sourceInformation));
|
| + pushStatement(new js.Break(_namer.implicitContinueLabelName(target))
|
| + .withSourceInformation(node.sourceInformation));
|
| } else {
|
| pushStatement(
|
| new js.Break(null).withSourceInformation(node.sourceInformation));
|
| @@ -1506,7 +1539,7 @@ 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))
|
| + pushStatement(new js.Continue(_namer.breakLabelName(label))
|
| .withSourceInformation(node.sourceInformation));
|
| }
|
| } else {
|
| @@ -1514,7 +1547,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| if (!tryCallAction(continueAction, target)) {
|
| if (target.isSwitch) {
|
| pushStatement(
|
| - new js.Continue(backend.namer.implicitContinueLabelName(target))
|
| + new js.Continue(_namer.implicitContinueLabelName(target))
|
| .withSourceInformation(node.sourceInformation));
|
| } else {
|
| pushStatement(new js.Continue(null)
|
| @@ -1536,7 +1569,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| visitTry(HTry node) {
|
| // We should never get here. Try/catch/finally is always handled using block
|
| // information in [visitTryInfo].
|
| - reporter.internalError(node, 'visitTry should not be called.');
|
| + throw new SpannableAssertionFailure(node, 'visitTry should not be called.');
|
| }
|
|
|
| bool tryControlFlowOperation(HIf node) {
|
| @@ -1635,17 +1668,16 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| push(js.js('# && #', [receiverExpression, constant]));
|
| } else {
|
| assert(node.inputs.length == 1);
|
| - registry.registerSpecializedGetInterceptor(node.interceptedClasses);
|
| - js.Name name =
|
| - backend.namer.nameForGetInterceptor(node.interceptedClasses);
|
| + _registry.registerSpecializedGetInterceptor(node.interceptedClasses);
|
| + js.Name name = _namer.nameForGetInterceptor(node.interceptedClasses);
|
| var isolate = new js.VariableUse(
|
| - backend.namer.globalObjectForLibrary(helpers.interceptorsLibrary));
|
| + _namer.globalObjectForLibrary(_helpers.interceptorsLibrary));
|
| use(node.receiver);
|
| List<js.Expression> arguments = <js.Expression>[pop()];
|
| push(js
|
| .propertyCall(isolate, name, arguments)
|
| .withSourceInformation(node.sourceInformation));
|
| - registry.registerUseInterceptor();
|
| + _registry.registerUseInterceptor();
|
| }
|
| }
|
|
|
| @@ -1658,31 +1690,31 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
|
|
| // TODO(herhut): The namer should return the appropriate backendname here.
|
| if (target != null && !node.isInterceptedCall) {
|
| - if (target == helpers.jsArrayAdd) {
|
| + if (target == _helpers.jsArrayAdd) {
|
| methodName = 'push';
|
| - } else if (target == helpers.jsArrayRemoveLast) {
|
| + } else if (target == _helpers.jsArrayRemoveLast) {
|
| methodName = 'pop';
|
| - } else if (target == helpers.jsStringSplit) {
|
| + } else if (target == _helpers.jsStringSplit) {
|
| methodName = 'split';
|
| // Split returns a List, so we make sure the backend knows the
|
| // list class is instantiated.
|
| - registry.registerInstantiatedClass(commonElements.listClass);
|
| - } else if (backend.nativeData.isNativeMember(target) &&
|
| + _registry.registerInstantiatedClass(_commonElements.listClass);
|
| + } else if (_nativeData.isNativeMember(target) &&
|
| target.isFunction &&
|
| !node.isInterceptedCall) {
|
| // A direct (i.e. non-interceptor) native call is the result of
|
| // optimization. The optimization ensures any type checks or
|
| // conversions have been satisified.
|
| - methodName = backend.nativeData.getFixedBackendName(target);
|
| + methodName = _nativeData.getFixedBackendName(target);
|
| }
|
| }
|
|
|
| js.Name methodLiteral;
|
| if (methodName == null) {
|
| - methodLiteral = backend.namer.invocationName(node.selector);
|
| + methodLiteral = _namer.invocationName(node.selector);
|
| registerMethodInvoke(node);
|
| } else {
|
| - methodLiteral = backend.namer.asName(methodName);
|
| + methodLiteral = _namer.asName(methodName);
|
| }
|
| push(js
|
| .propertyCall(object, methodLiteral, arguments)
|
| @@ -1692,22 +1724,22 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| void visitInvokeConstructorBody(HInvokeConstructorBody node) {
|
| use(node.inputs[0]);
|
| js.Expression object = pop();
|
| - js.Name methodName = backend.namer.instanceMethodName(node.element);
|
| + js.Name methodName = _namer.instanceMethodName(node.element);
|
| List<js.Expression> arguments = visitArguments(node.inputs);
|
| push(js
|
| .propertyCall(object, methodName, arguments)
|
| .withSourceInformation(node.sourceInformation));
|
| - registry.registerStaticUse(new StaticUse.constructorBodyInvoke(
|
| + _registry.registerStaticUse(new StaticUse.constructorBodyInvoke(
|
| node.element, new CallStructure.unnamed(arguments.length)));
|
| }
|
|
|
| void visitOneShotInterceptor(HOneShotInterceptor node) {
|
| List<js.Expression> arguments = visitArguments(node.inputs);
|
| var isolate = new js.VariableUse(
|
| - backend.namer.globalObjectForLibrary(helpers.interceptorsLibrary));
|
| + _namer.globalObjectForLibrary(_helpers.interceptorsLibrary));
|
| Selector selector = node.selector;
|
| - js.Name methodName = backend.oneShotInterceptorData
|
| - .registerOneShotInterceptor(selector, backend.namer);
|
| + js.Name methodName =
|
| + _oneShotInterceptorData.registerOneShotInterceptor(selector, _namer);
|
| push(js
|
| .propertyCall(isolate, methodName, arguments)
|
| .withSourceInformation(node.sourceInformation));
|
| @@ -1718,7 +1750,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| } else {
|
| registerMethodInvoke(node);
|
| }
|
| - registry.registerUseInterceptor();
|
| + _registry.registerUseInterceptor();
|
| }
|
|
|
| TypeMask getOptimizedSelectorFor(
|
| @@ -1729,20 +1761,20 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| // type because our optimizations might end up in a state where the
|
| // invoke dynamic knows more than the receiver.
|
| ClassEntity enclosing = node.element.enclosingClass;
|
| - if (closedWorld.isInstantiated(enclosing)) {
|
| - return closedWorld.commonMasks.createNonNullExact(enclosing);
|
| + if (_closedWorld.isInstantiated(enclosing)) {
|
| + return _closedWorld.commonMasks.createNonNullExact(enclosing);
|
| } else {
|
| // The element is mixed in so a non-null subtype mask is the most
|
| // precise we have.
|
| - assert(invariant(node, closedWorld.isUsedAsMixin(enclosing),
|
| + assert(invariant(node, _closedWorld.isUsedAsMixin(enclosing),
|
| message: "Element ${node.element} from $enclosing expected "
|
| "to be mixed in."));
|
| - return closedWorld.commonMasks.createNonNullSubtype(enclosing);
|
| + return _closedWorld.commonMasks.createNonNullSubtype(enclosing);
|
| }
|
| }
|
| // If [JSInvocationMirror._invokeOn] is enabled, and this call
|
| // might hit a `noSuchMethod`, we register an untyped selector.
|
| - return closedWorld.extendMaskIfReachesAll(selector, mask);
|
| + return _closedWorld.extendMaskIfReachesAll(selector, mask);
|
| }
|
|
|
| void registerMethodInvoke(HInvokeDynamic node) {
|
| @@ -1757,7 +1789,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| // may know something about the types of closures that need
|
| // the specific closure call method.
|
| Selector call = new Selector.callClosureFrom(selector);
|
| - registry.registerDynamicUse(new DynamicUse(call, null));
|
| + _registry.registerDynamicUse(new DynamicUse(call, null));
|
| }
|
| if (target != null) {
|
| // This is a dynamic invocation which we have found to have a single
|
| @@ -1766,11 +1798,11 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| // for this to work.
|
| assert(invariant(node, selector.applies(target),
|
| message: '$selector does not apply to $target'));
|
| - registry.registerStaticUse(
|
| + _registry.registerStaticUse(
|
| new StaticUse.directInvoke(target, selector.callStructure));
|
| } else {
|
| TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask);
|
| - registry.registerDynamicUse(new DynamicUse(selector, mask));
|
| + _registry.registerDynamicUse(new DynamicUse(selector, mask));
|
| }
|
| }
|
|
|
| @@ -1780,11 +1812,11 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| // target but for some reason haven't inlined. We are _still_ accessing
|
| // the target dynamically but we don't need to enqueue more than target
|
| // for this to work.
|
| - registry.registerStaticUse(new StaticUse.directSet(node.element));
|
| + _registry.registerStaticUse(new StaticUse.directSet(node.element));
|
| } else {
|
| Selector selector = node.selector;
|
| TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask);
|
| - registry.registerDynamicUse(new DynamicUse(selector, mask));
|
| + _registry.registerDynamicUse(new DynamicUse(selector, mask));
|
| }
|
| }
|
|
|
| @@ -1796,17 +1828,17 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| // dynamically but we don't need to enqueue more than target for this to
|
| // work. The test above excludes non-getter functions since the element
|
| // represents two targets - a tearoff getter and the torn-off method.
|
| - registry.registerStaticUse(new StaticUse.directGet(node.element));
|
| + _registry.registerStaticUse(new StaticUse.directGet(node.element));
|
| } else {
|
| Selector selector = node.selector;
|
| TypeMask mask = getOptimizedSelectorFor(node, selector, node.mask);
|
| - registry.registerDynamicUse(new DynamicUse(selector, mask));
|
| + _registry.registerDynamicUse(new DynamicUse(selector, mask));
|
| }
|
| }
|
|
|
| visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
|
| use(node.receiver);
|
| - js.Name name = backend.namer.invocationName(node.selector);
|
| + js.Name name = _namer.invocationName(node.selector);
|
| push(js
|
| .propertyCall(pop(), name, visitArguments(node.inputs))
|
| .withSourceInformation(node.sourceInformation));
|
| @@ -1815,7 +1847,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
|
|
| visitInvokeDynamicGetter(HInvokeDynamicGetter node) {
|
| use(node.receiver);
|
| - js.Name name = backend.namer.invocationName(node.selector);
|
| + js.Name name = _namer.invocationName(node.selector);
|
| push(js
|
| .propertyCall(pop(), name, visitArguments(node.inputs))
|
| .withSourceInformation(node.sourceInformation));
|
| @@ -1826,10 +1858,10 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| Selector call = new Selector.callClosureFrom(node.selector);
|
| use(node.receiver);
|
| push(js
|
| - .propertyCall(pop(), backend.namer.invocationName(call),
|
| - visitArguments(node.inputs))
|
| + .propertyCall(
|
| + pop(), _namer.invocationName(call), visitArguments(node.inputs))
|
| .withSourceInformation(node.sourceInformation));
|
| - registry.registerDynamicUse(new DynamicUse(call, null));
|
| + _registry.registerDynamicUse(new DynamicUse(call, null));
|
| }
|
|
|
| visitInvokeStatic(HInvokeStatic node) {
|
| @@ -1838,13 +1870,13 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
|
|
| if (instantiatedTypes != null && !instantiatedTypes.isEmpty) {
|
| instantiatedTypes.forEach((type) {
|
| - registry.registerInstantiation(type);
|
| + _registry.registerInstantiation(type);
|
| });
|
| }
|
|
|
| List<js.Expression> arguments = visitArguments(node.inputs, start: 0);
|
|
|
| - if (element == backend.helpers.checkConcurrentModificationError) {
|
| + if (element == _helpers.checkConcurrentModificationError) {
|
| // Manually inline the [checkConcurrentModificationError] function. This
|
| // function is only called from a for-loop update. Ideally we would just
|
| // generate the conditionalcontrol flow in the builder but it adds basic
|
| @@ -1852,9 +1884,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| // confuses loop recognition.
|
|
|
| assert(arguments.length == 2);
|
| - FunctionEntity throwFunction =
|
| - backend.helpers.throwConcurrentModificationError;
|
| - registry.registerStaticUse(
|
| + FunctionEntity throwFunction = _helpers.throwConcurrentModificationError;
|
| + _registry.registerStaticUse(
|
| new StaticUse.staticInvoke(throwFunction, CallStructure.ONE_ARG));
|
|
|
| // Calling using `(0, #)(#)` instead of `#(#)` separates the property load
|
| @@ -1866,15 +1897,15 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| // modification check.
|
| push(js.js('# || (0, #)(#)', [
|
| arguments[0],
|
| - backend.emitter.staticFunctionAccess(throwFunction),
|
| + _emitter.staticFunctionAccess(throwFunction),
|
| arguments[1]
|
| ]));
|
| } else {
|
| CallStructure callStructure = new CallStructure.unnamed(arguments.length);
|
| - registry.registerStaticUse(element.isConstructor
|
| + _registry.registerStaticUse(element.isConstructor
|
| ? new StaticUse.constructorInvoke(element, callStructure)
|
| : new StaticUse.staticInvoke(element, callStructure));
|
| - push(backend.emitter.staticFunctionAccess(element));
|
| + push(_emitter.staticFunctionAccess(element));
|
| push(new js.Call(pop(), arguments,
|
| sourceInformation: node.sourceInformation));
|
| }
|
| @@ -1884,53 +1915,52 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| MemberEntity superElement = node.element;
|
| ClassEntity superClass = superElement.enclosingClass;
|
| if (superElement.isField) {
|
| - js.Name fieldName = backend.namer.instanceFieldPropertyName(superElement);
|
| + js.Name fieldName = _namer.instanceFieldPropertyName(superElement);
|
| use(node.inputs[0]);
|
| js.PropertyAccess access = new js.PropertyAccess(pop(), fieldName)
|
| .withSourceInformation(node.sourceInformation);
|
| if (node.isSetter) {
|
| - registry.registerStaticUse(superElement.isSetter
|
| + _registry.registerStaticUse(superElement.isSetter
|
| ? new StaticUse.superSetterSet(superElement)
|
| : new StaticUse.superFieldSet(superElement));
|
| use(node.value);
|
| push(new js.Assignment(access, pop())
|
| .withSourceInformation(node.sourceInformation));
|
| } else {
|
| - registry.registerStaticUse(new StaticUse.superGet(superElement));
|
| + _registry.registerStaticUse(new StaticUse.superGet(superElement));
|
| push(access);
|
| }
|
| } else {
|
| Selector selector = node.selector;
|
| - if (!backend.superMemberData
|
| - .maybeRegisterAliasedSuperMember(superElement, selector)) {
|
| + if (!_superMemberData.maybeRegisterAliasedSuperMember(
|
| + superElement, selector)) {
|
| js.Name methodName;
|
| if (selector.isGetter && !superElement.isGetter) {
|
| // If this is a tear-off, register the fact that a tear-off closure
|
| // will be created, and that this tear-off must bypass ordinary
|
| // dispatch to ensure the super method is invoked.
|
| - FunctionEntity helper = backend.helpers.closureFromTearOff;
|
| - registry.registerStaticUse(new StaticUse.staticInvoke(
|
| + FunctionEntity helper = _helpers.closureFromTearOff;
|
| + _registry.registerStaticUse(new StaticUse.staticInvoke(
|
| helper, new CallStructure.unnamed(node.inputs.length)));
|
| - registry.registerStaticUse(new StaticUse.superTearOff(node.element));
|
| - methodName = backend.namer.invocationName(selector);
|
| + _registry.registerStaticUse(new StaticUse.superTearOff(node.element));
|
| + methodName = _namer.invocationName(selector);
|
| } else {
|
| - methodName = backend.namer.instanceMethodName(superElement);
|
| + methodName = _namer.instanceMethodName(superElement);
|
| }
|
| - registry.registerStaticUse(new StaticUse.superInvoke(
|
| + _registry.registerStaticUse(new StaticUse.superInvoke(
|
| superElement, new CallStructure.unnamed(node.inputs.length)));
|
| push(js.js('#.#.call(#)', [
|
| - backend.emitter
|
| - .prototypeAccess(superClass, hasBeenInstantiated: true),
|
| + _emitter.prototypeAccess(superClass, hasBeenInstantiated: true),
|
| methodName,
|
| visitArguments(node.inputs, start: 0)
|
| ]).withSourceInformation(node.sourceInformation));
|
| } else {
|
| use(node.receiver);
|
| - registry.registerStaticUse(new StaticUse.superInvoke(
|
| + _registry.registerStaticUse(new StaticUse.superInvoke(
|
| superElement, new CallStructure.unnamed(node.inputs.length - 1)));
|
| push(js.js('#.#(#)', [
|
| pop(),
|
| - backend.namer.aliasedSuperMemberPropertyName(superElement),
|
| + _namer.aliasedSuperMemberPropertyName(superElement),
|
| visitArguments(node.inputs, start: 1)
|
| ]) // Skip receiver argument.
|
| .withSourceInformation(node.sourceInformation));
|
| @@ -1948,17 +1978,17 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| .withSourceInformation(node.sourceInformation));
|
| } else {
|
| FieldEntity field = node.element;
|
| - js.Name name = backend.namer.instanceFieldPropertyName(field);
|
| + js.Name name = _namer.instanceFieldPropertyName(field);
|
| push(new js.PropertyAccess(pop(), name)
|
| .withSourceInformation(node.sourceInformation));
|
| - registry.registerStaticUse(new StaticUse.fieldGet(field));
|
| + _registry.registerStaticUse(new StaticUse.fieldGet(field));
|
| }
|
| }
|
|
|
| visitFieldSet(HFieldSet node) {
|
| FieldEntity element = node.element;
|
| - registry.registerStaticUse(new StaticUse.fieldSet(element));
|
| - js.Name name = backend.namer.instanceFieldPropertyName(element);
|
| + _registry.registerStaticUse(new StaticUse.fieldSet(element));
|
| + js.Name name = _namer.instanceFieldPropertyName(element);
|
| use(node.receiver);
|
| js.Expression receiver = pop();
|
| use(node.value);
|
| @@ -1974,9 +2004,9 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
|
|
| visitReadModifyWrite(HReadModifyWrite node) {
|
| FieldEntity element = node.element;
|
| - registry.registerStaticUse(new StaticUse.fieldGet(element));
|
| - registry.registerStaticUse(new StaticUse.fieldSet(element));
|
| - js.Name name = backend.namer.instanceFieldPropertyName(element);
|
| + _registry.registerStaticUse(new StaticUse.fieldGet(element));
|
| + _registry.registerStaticUse(new StaticUse.fieldSet(element));
|
| + js.Name name = _namer.instanceFieldPropertyName(element);
|
| use(node.receiver);
|
| js.Expression fieldReference = new js.PropertyAccess(pop(), name);
|
| if (node.isPreOp) {
|
| @@ -2005,8 +2035,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| void registerForeignTypes(HForeign node) {
|
| native.NativeBehavior nativeBehavior = node.nativeBehavior;
|
| if (nativeBehavior == null) return;
|
| - nativeEnqueuer.registerNativeBehavior(
|
| - registry.worldImpact, nativeBehavior, node);
|
| + _nativeEnqueuer.registerNativeBehavior(
|
| + _registry.worldImpact, nativeBehavior, node);
|
| }
|
|
|
| visitForeignCode(HForeignCode node) {
|
| @@ -2035,14 +2065,13 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| registerForeignTypes(node);
|
|
|
| if (node.foreignFunction != null) {
|
| - registry?.registerStaticUse(
|
| + _registry?.registerStaticUse(
|
| new StaticUse.implicitInvoke(node.foreignFunction));
|
| }
|
| }
|
|
|
| visitCreate(HCreate node) {
|
| - js.Expression jsClassReference =
|
| - backend.emitter.constructorAccess(node.element);
|
| + js.Expression jsClassReference = _emitter.constructorAccess(node.element);
|
| List<js.Expression> arguments = visitArguments(node.inputs, start: 0);
|
| push(new js.New(jsClassReference, arguments)
|
| .withSourceInformation(node.sourceInformation));
|
| @@ -2050,21 +2079,21 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| // function expressions. We have to register their use here, as otherwise
|
| // code for them might not be emitted.
|
| if (node.element.isClosure) {
|
| - registry.registerInstantiatedClass(node.element);
|
| + _registry.registerInstantiatedClass(node.element);
|
| }
|
| - node.instantiatedTypes?.forEach(registry.registerInstantiation);
|
| + node.instantiatedTypes?.forEach(_registry.registerInstantiation);
|
| if (node.callMethod != null) {
|
| - registry
|
| + _registry
|
| ?.registerStaticUse(new StaticUse.implicitInvoke(node.callMethod));
|
| }
|
| if (node.localFunction != null) {
|
| - registry?.registerInstantiatedClosure(node.localFunction);
|
| + _registry?.registerInstantiatedClosure(node.localFunction);
|
| }
|
| }
|
|
|
| js.Expression newLiteralBool(
|
| bool value, SourceInformation sourceInformation) {
|
| - if (compiler.options.enableMinification) {
|
| + if (_options.enableMinification) {
|
| // Use !0 for true, !1 for false.
|
| return new js.Prefix("!", new js.LiteralNumber(value ? "0" : "1"))
|
| .withSourceInformation(sourceInformation);
|
| @@ -2075,7 +2104,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
|
|
| void generateConstant(
|
| ConstantValue constant, SourceInformation sourceInformation) {
|
| - js.Expression expression = backend.emitter.constantReference(constant);
|
| + js.Expression expression = _emitter.constantReference(constant);
|
| if (!constant.isDummy) {
|
| // TODO(johnniwinther): Support source information on synthetic constants.
|
| expression = expression.withSourceInformation(sourceInformation);
|
| @@ -2087,7 +2116,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| assert(isGenerateAtUseSite(node));
|
| generateConstant(node.constant, node.sourceInformation);
|
|
|
| - registry.registerConstantUse(new ConstantUse.literal(node.constant));
|
| + _registry.registerConstantUse(new ConstantUse.literal(node.constant));
|
| }
|
|
|
| visitNot(HNot node) {
|
| @@ -2117,14 +2146,14 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
|
|
| HInstruction left = relational.left;
|
| HInstruction right = relational.right;
|
| - if (left.isStringOrNull(closedWorld) &&
|
| - right.isStringOrNull(closedWorld)) {
|
| + if (left.isStringOrNull(_closedWorld) &&
|
| + right.isStringOrNull(_closedWorld)) {
|
| return true;
|
| }
|
|
|
| // This optimization doesn't work for NaN, so we only do it if the
|
| // type is known to be an integer.
|
| - return left.isInteger(closedWorld) && right.isInteger(closedWorld);
|
| + return left.isInteger(_closedWorld) && right.isInteger(_closedWorld);
|
| }
|
|
|
| bool handledBySpecialCase = false;
|
| @@ -2145,8 +2174,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| .withSourceInformation(sourceInformation));
|
| } else if (canGenerateOptimizedComparison(input)) {
|
| HRelational relational = input;
|
| - BinaryOperation operation =
|
| - relational.operation(backend.constantSystem);
|
| + BinaryOperation operation = relational.operation(_constantSystem);
|
| String op = mapRelationalOperator(operation.name, true);
|
| handleInvokeBinary(input, op, sourceInformation);
|
| } else {
|
| @@ -2226,7 +2254,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| pushStatement(
|
| new js.Throw(pop()).withSourceInformation(node.sourceInformation));
|
| } else {
|
| - generateThrowWithHelper(helpers.wrapExceptionHelper, node.inputs[0],
|
| + generateThrowWithHelper(_helpers.wrapExceptionHelper, node.inputs[0],
|
| sourceInformation: node.sourceInformation);
|
| }
|
| }
|
| @@ -2260,13 +2288,13 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| js.Expression over;
|
| if (node.staticChecks != HBoundsCheck.ALWAYS_ABOVE_ZERO) {
|
| use(node.index);
|
| - if (node.index.isInteger(closedWorld)) {
|
| + if (node.index.isInteger(_closedWorld)) {
|
| under = js.js("# < 0", pop());
|
| } else {
|
| js.Expression jsIndex = pop();
|
| under = js.js("# >>> 0 !== #", [jsIndex, jsIndex]);
|
| }
|
| - } else if (!node.index.isInteger(closedWorld)) {
|
| + } else if (!node.index.isInteger(_closedWorld)) {
|
| checkInt(node.index, '!==');
|
| under = pop();
|
| }
|
| @@ -2284,7 +2312,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| js.Statement thenBody = new js.Block.empty();
|
| js.Block oldContainer = currentContainer;
|
| currentContainer = thenBody;
|
| - generateThrowWithHelper(helpers.throwIndexOutOfRangeException,
|
| + generateThrowWithHelper(_helpers.throwIndexOutOfRangeException,
|
| [node.array, node.reportedIndex]);
|
| currentContainer = oldContainer;
|
| thenBody = unwrapStatement(thenBody);
|
| @@ -2292,13 +2320,13 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| .withSourceInformation(node.sourceInformation));
|
| } else {
|
| generateThrowWithHelper(
|
| - helpers.throwIndexOutOfRangeException, [node.array, node.index]);
|
| + _helpers.throwIndexOutOfRangeException, [node.array, node.index]);
|
| }
|
| }
|
|
|
| void generateThrowWithHelper(FunctionEntity helper, argument,
|
| {SourceInformation sourceInformation}) {
|
| - js.Expression jsHelper = backend.emitter.staticFunctionAccess(helper);
|
| + js.Expression jsHelper = _emitter.staticFunctionAccess(helper);
|
| List arguments = [];
|
| if (argument is List) {
|
| argument.forEach((instruction) {
|
| @@ -2309,18 +2337,18 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| use(argument);
|
| arguments.add(pop());
|
| }
|
| - registry.registerStaticUse(new StaticUse.staticInvoke(
|
| + _registry.registerStaticUse(new StaticUse.staticInvoke(
|
| helper, new CallStructure.unnamed(arguments.length)));
|
| 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 (helper == helpers.wrapExceptionHelper) {
|
| + if (helper == _helpers.wrapExceptionHelper) {
|
| pushStatement(
|
| new js.Throw(value).withSourceInformation(sourceInformation));
|
| } else {
|
| - Entity element = work.element;
|
| + Entity element = _work.element;
|
| if (element is MethodElement && element.asyncMarker.isYielding) {
|
| // `return <expr>;` is illegal in a sync* or async* function.
|
| // To have the async-translator working, we avoid introducing
|
| @@ -2338,11 +2366,11 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| HInstruction argument = node.inputs[0];
|
| use(argument);
|
|
|
| - FunctionEntity helper = helpers.throwExpressionHelper;
|
| - registry.registerStaticUse(
|
| + FunctionEntity helper = _helpers.throwExpressionHelper;
|
| + _registry.registerStaticUse(
|
| new StaticUse.staticInvoke(helper, CallStructure.ONE_ARG));
|
|
|
| - js.Expression jsHelper = backend.emitter.staticFunctionAccess(helper);
|
| + js.Expression jsHelper = _emitter.staticFunctionAccess(helper);
|
| js.Call value = new js.Call(jsHelper, [pop()])
|
| .withSourceInformation(node.sourceInformation);
|
| push(value);
|
| @@ -2356,31 +2384,30 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| MemberEntity element = node.element;
|
| assert(element.isFunction || element.isField);
|
| if (element.isFunction) {
|
| - push(backend.emitter
|
| + push(_emitter
|
| .isolateStaticClosureAccess(element)
|
| .withSourceInformation(node.sourceInformation));
|
| - registry.registerStaticUse(new StaticUse.staticTearOff(element));
|
| + _registry.registerStaticUse(new StaticUse.staticTearOff(element));
|
| } else {
|
| - push(backend.emitter
|
| + push(_emitter
|
| .staticFieldAccess(element)
|
| .withSourceInformation(node.sourceInformation));
|
| - registry.registerStaticUse(new StaticUse.staticGet(element));
|
| + _registry.registerStaticUse(new StaticUse.staticGet(element));
|
| }
|
| }
|
|
|
| void visitLazyStatic(HLazyStatic node) {
|
| FieldEntity element = node.element;
|
| - registry.registerStaticUse(new StaticUse.staticInit(element));
|
| - js.Expression lazyGetter =
|
| - backend.emitter.isolateLazyInitializerAccess(element);
|
| + _registry.registerStaticUse(new StaticUse.staticInit(element));
|
| + js.Expression lazyGetter = _emitter.isolateLazyInitializerAccess(element);
|
| js.Call call = new js.Call(lazyGetter, <js.Expression>[],
|
| sourceInformation: node.sourceInformation);
|
| push(call);
|
| }
|
|
|
| void visitStaticStore(HStaticStore node) {
|
| - registry.registerStaticUse(new StaticUse.staticSet(node.element));
|
| - js.Node variable = backend.emitter.staticFieldAccess(node.element);
|
| + _registry.registerStaticUse(new StaticUse.staticSet(node.element));
|
| + js.Node variable = _emitter.staticFieldAccess(node.element);
|
| use(node.inputs[0]);
|
| push(new js.Assignment(variable, pop())
|
| .withSourceInformation(node.sourceInformation));
|
| @@ -2396,9 +2423,9 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
|
|
| void visitStringify(HStringify node) {
|
| HInstruction input = node.inputs.first;
|
| - if (input.isString(closedWorld)) {
|
| + if (input.isString(_closedWorld)) {
|
| use(input);
|
| - } else if (input.isInteger(closedWorld) || input.isBoolean(closedWorld)) {
|
| + } else if (input.isInteger(_closedWorld) || input.isBoolean(_closedWorld)) {
|
| // JavaScript's + operator with a string for the left operand will convert
|
| // the right operand to a string, and the conversion result is correct.
|
| use(input);
|
| @@ -2412,12 +2439,10 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| .withSourceInformation(node.sourceInformation));
|
| }
|
| } else {
|
| - FunctionEntity convertToString =
|
| - backend.helpers.stringInterpolationHelper;
|
| - registry.registerStaticUse(
|
| + FunctionEntity convertToString = _helpers.stringInterpolationHelper;
|
| + _registry.registerStaticUse(
|
| new StaticUse.staticInvoke(convertToString, CallStructure.ONE_ARG));
|
| - js.Expression jsHelper =
|
| - backend.emitter.staticFunctionAccess(convertToString);
|
| + js.Expression jsHelper = _emitter.staticFunctionAccess(convertToString);
|
| use(input);
|
| push(new js.Call(jsHelper, <js.Expression>[pop()],
|
| sourceInformation: node.sourceInformation));
|
| @@ -2425,7 +2450,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| }
|
|
|
| void visitLiteralList(HLiteralList node) {
|
| - registry.registerInstantiatedClass(commonElements.listClass);
|
| + _registry.registerInstantiatedClass(_commonElements.listClass);
|
| generateArrayLiteral(node);
|
| }
|
|
|
| @@ -2575,31 +2600,31 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| if (type.isInterfaceType) {
|
| InterfaceType interfaceType = type;
|
| ClassEntity element = interfaceType.element;
|
| - if (element == helpers.jsArrayClass) {
|
| + if (element == _helpers.jsArrayClass) {
|
| checkArray(input, negative ? '!==' : '===');
|
| return;
|
| - } else if (element == helpers.jsMutableArrayClass) {
|
| + } else if (element == _helpers.jsMutableArrayClass) {
|
| if (negative) {
|
| checkImmutableArray(input);
|
| } else {
|
| checkMutableArray(input);
|
| }
|
| return;
|
| - } else if (element == helpers.jsExtendableArrayClass) {
|
| + } else if (element == _helpers.jsExtendableArrayClass) {
|
| if (negative) {
|
| checkFixedArray(input);
|
| } else {
|
| checkExtendableArray(input);
|
| }
|
| return;
|
| - } else if (element == helpers.jsFixedArrayClass) {
|
| + } else if (element == _helpers.jsFixedArrayClass) {
|
| if (negative) {
|
| checkExtendableArray(input);
|
| } else {
|
| checkFixedArray(input);
|
| }
|
| return;
|
| - } else if (element == helpers.jsUnmodifiableArrayClass) {
|
| + } else if (element == _helpers.jsUnmodifiableArrayClass) {
|
| if (negative) {
|
| checkMutableArray(input);
|
| } else {
|
| @@ -2619,12 +2644,12 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| void checkTypeViaProperty(
|
| HInstruction input, DartType type, SourceInformation sourceInformation,
|
| {bool negative: false}) {
|
| - registry.registerTypeUse(new TypeUse.isCheck(type));
|
| + _registry.registerTypeUse(new TypeUse.isCheck(type));
|
|
|
| use(input);
|
|
|
| js.PropertyAccess field =
|
| - new js.PropertyAccess(pop(), backend.namer.operatorIsType(type))
|
| + new js.PropertyAccess(pop(), _namer.operatorIsType(type))
|
| .withSourceInformation(sourceInformation);
|
| // We always negate at least once so that the result is boolified.
|
| push(new js.Prefix('!', field).withSourceInformation(sourceInformation));
|
| @@ -2637,18 +2662,17 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| void checkTypeViaInstanceof(HInstruction input, InterfaceType type,
|
| SourceInformation sourceInformation,
|
| {bool negative: false}) {
|
| - registry.registerTypeUse(new TypeUse.isCheck(type));
|
| + _registry.registerTypeUse(new TypeUse.isCheck(type));
|
|
|
| use(input);
|
|
|
| - js.Expression jsClassReference =
|
| - backend.emitter.constructorAccess(type.element);
|
| + js.Expression jsClassReference = _emitter.constructorAccess(type.element);
|
| push(js.js('# instanceof #',
|
| [pop(), jsClassReference]).withSourceInformation(sourceInformation));
|
| if (negative) {
|
| push(new js.Prefix('!', pop()).withSourceInformation(sourceInformation));
|
| }
|
| - registry.registerInstantiation(type);
|
| + _registry.registerInstantiation(type);
|
| }
|
|
|
| void handleNumberOrStringSupertypeCheck(
|
| @@ -2657,9 +2681,9 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| InterfaceType type,
|
| SourceInformation sourceInformation,
|
| {bool negative: false}) {
|
| - assert(!identical(type.element, commonElements.listClass) &&
|
| - !commonElements.isListSupertype(type.element) &&
|
| - !commonElements.isStringOnlySupertype(type.element));
|
| + assert(!identical(type.element, _commonElements.listClass) &&
|
| + !_commonElements.isListSupertype(type.element) &&
|
| + !_commonElements.isStringOnlySupertype(type.element));
|
| String relation = negative ? '!==' : '===';
|
| checkNum(input, relation, sourceInformation);
|
| js.Expression numberTest = pop();
|
| @@ -2682,9 +2706,9 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| void handleStringSupertypeCheck(HInstruction input, HInstruction interceptor,
|
| InterfaceType type, SourceInformation sourceInformation,
|
| {bool negative: false}) {
|
| - assert(!identical(type.element, commonElements.listClass) &&
|
| - !commonElements.isListSupertype(type.element) &&
|
| - !commonElements.isNumberOrStringSupertype(type.element));
|
| + assert(!identical(type.element, _commonElements.listClass) &&
|
| + !_commonElements.isListSupertype(type.element) &&
|
| + !_commonElements.isNumberOrStringSupertype(type.element));
|
| String relation = negative ? '!==' : '===';
|
| checkString(input, relation, sourceInformation);
|
| js.Expression stringTest = pop();
|
| @@ -2699,9 +2723,9 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| void handleListOrSupertypeCheck(HInstruction input, HInstruction interceptor,
|
| InterfaceType type, SourceInformation sourceInformation,
|
| {bool negative: false}) {
|
| - assert(!identical(type.element, commonElements.stringClass) &&
|
| - !commonElements.isStringOnlySupertype(type.element) &&
|
| - !commonElements.isNumberOrStringSupertype(type.element));
|
| + assert(!identical(type.element, _commonElements.stringClass) &&
|
| + !_commonElements.isStringOnlySupertype(type.element) &&
|
| + !_commonElements.isNumberOrStringSupertype(type.element));
|
| String relation = negative ? '!==' : '===';
|
| checkObject(input, relation, sourceInformation);
|
| js.Expression objectTest = pop();
|
| @@ -2724,7 +2748,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
|
|
| void emitIs(HIs node, String relation, SourceInformation sourceInformation) {
|
| DartType type = node.typeExpression;
|
| - registry.registerTypeUse(new TypeUse.isCheck(type));
|
| + _registry.registerTypeUse(new TypeUse.isCheck(type));
|
| HInstruction input = node.expression;
|
|
|
| // If this is changed to single == there are several places below that must
|
| @@ -2740,26 +2764,26 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| HInstruction interceptor = node.interceptor;
|
| InterfaceType interfaceType = type;
|
| ClassEntity element = interfaceType.element;
|
| - if (element == commonElements.nullClass) {
|
| + if (element == _commonElements.nullClass) {
|
| if (negative) {
|
| checkNonNull(input);
|
| } else {
|
| checkNull(input);
|
| }
|
| } else if (element ==
|
| - commonElements.objectClass /* || type.treatAsDynamic*/) {
|
| + _commonElements.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, sourceInformation));
|
| - } else if (element == commonElements.stringClass) {
|
| + } else if (element == _commonElements.stringClass) {
|
| checkString(input, relation, sourceInformation);
|
| - } else if (element == commonElements.doubleClass) {
|
| + } else if (element == _commonElements.doubleClass) {
|
| checkDouble(input, relation, sourceInformation);
|
| - } else if (element == commonElements.numClass) {
|
| + } else if (element == _commonElements.numClass) {
|
| checkNum(input, relation, sourceInformation);
|
| - } else if (element == commonElements.boolClass) {
|
| + } else if (element == _commonElements.boolClass) {
|
| checkBool(input, relation, sourceInformation);
|
| - } else if (element == commonElements.intClass) {
|
| + } else if (element == _commonElements.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.
|
| @@ -2772,22 +2796,22 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| assert(interceptor == null);
|
| checkTypeViaInstanceof(input, type, sourceInformation,
|
| negative: negative);
|
| - } else if (commonElements.isNumberOrStringSupertype(element)) {
|
| + } else if (_commonElements.isNumberOrStringSupertype(element)) {
|
| handleNumberOrStringSupertypeCheck(
|
| input, interceptor, type, sourceInformation,
|
| negative: negative);
|
| - } else if (commonElements.isStringOnlySupertype(element)) {
|
| + } else if (_commonElements.isStringOnlySupertype(element)) {
|
| handleStringSupertypeCheck(input, interceptor, type, sourceInformation,
|
| negative: negative);
|
| - } else if (element == commonElements.listClass ||
|
| - commonElements.isListSupertype(element)) {
|
| + } else if (element == _commonElements.listClass ||
|
| + _commonElements.isListSupertype(element)) {
|
| handleListOrSupertypeCheck(input, interceptor, type, sourceInformation,
|
| negative: negative);
|
| } else if (type.isFunctionType) {
|
| checkType(input, interceptor, type, sourceInformation,
|
| negative: negative);
|
| - } else if ((input.canBePrimitive(closedWorld) &&
|
| - !input.canBePrimitiveArray(closedWorld)) ||
|
| + } else if ((input.canBePrimitive(_closedWorld) &&
|
| + !input.canBePrimitiveArray(_closedWorld)) ||
|
| input.canBeNull()) {
|
| checkObject(input, relation, node.sourceInformation);
|
| js.Expression objectTest = pop();
|
| @@ -2818,13 +2842,13 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| // V8 generally prefers 'typeof' checks, but for integers and
|
| // indexable primitives we cannot compile this test into a single
|
| // typeof check so the null check is cheaper.
|
| - bool isIntCheck = checkedType.containsOnlyInt(closedWorld);
|
| + bool isIntCheck = checkedType.containsOnlyInt(_closedWorld);
|
| bool turnIntoNumCheck =
|
| - isIntCheck && inputType.containsOnlyInt(closedWorld);
|
| + isIntCheck && inputType.containsOnlyInt(_closedWorld);
|
| bool turnIntoNullCheck = !turnIntoNumCheck &&
|
| (checkedType.nullable() == inputType) &&
|
| (isIntCheck ||
|
| - checkedType.satisfies(helpers.jsIndexableClass, closedWorld));
|
| + checkedType.satisfies(_helpers.jsIndexableClass, _closedWorld));
|
|
|
| if (turnIntoNullCheck) {
|
| use(input);
|
| @@ -2834,21 +2858,21 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| // input is !int
|
| checkBigInt(input, '!==', input.sourceInformation);
|
| return pop();
|
| - } else if (turnIntoNumCheck || checkedType.containsOnlyNum(closedWorld)) {
|
| + } else if (turnIntoNumCheck || checkedType.containsOnlyNum(_closedWorld)) {
|
| // input is !num
|
| checkNum(input, '!==', input.sourceInformation);
|
| return pop();
|
| - } else if (checkedType.containsOnlyBool(closedWorld)) {
|
| + } else if (checkedType.containsOnlyBool(_closedWorld)) {
|
| // input is !bool
|
| checkBool(input, '!==', input.sourceInformation);
|
| return pop();
|
| - } else if (checkedType.containsOnlyString(closedWorld)) {
|
| + } else if (checkedType.containsOnlyString(_closedWorld)) {
|
| // input is !string
|
| checkString(input, '!==', input.sourceInformation);
|
| return pop();
|
| }
|
| - reporter.internalError(input, 'Unexpected check: $checkedType.');
|
| - return null;
|
| + throw new SpannableAssertionFailure(
|
| + input, 'Unexpected check: $checkedType.');
|
| }
|
|
|
| void visitTypeConversion(HTypeConversion node) {
|
| @@ -2859,12 +2883,12 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| currentContainer = body;
|
| if (node.isArgumentTypeCheck) {
|
| generateThrowWithHelper(
|
| - helpers.throwIllegalArgumentException, node.checkedInput,
|
| + _helpers.throwIllegalArgumentException, node.checkedInput,
|
| sourceInformation: node.sourceInformation);
|
| } else if (node.isReceiverTypeCheck) {
|
| use(node.checkedInput);
|
| js.Name methodName =
|
| - backend.namer.invocationName(node.receiverTypeCheckSelector);
|
| + _namer.invocationName(node.receiverTypeCheckSelector);
|
| js.Expression call = js.propertyCall(pop(), methodName, []);
|
| pushStatement(new js.Return(call));
|
| }
|
| @@ -2882,20 +2906,27 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| if (type.isFunctionType) {
|
| // TODO(5022): We currently generate $isFunction checks for
|
| // function types.
|
| - registry.registerTypeUse(
|
| - new TypeUse.isCheck(compiler.commonElements.functionType));
|
| + _registry
|
| + .registerTypeUse(new TypeUse.isCheck(_commonElements.functionType));
|
| }
|
| - registry.registerTypeUse(new TypeUse.isCheck(type));
|
| + _registry.registerTypeUse(new TypeUse.isCheck(type));
|
|
|
| CheckedModeHelper helper;
|
| if (node.isBooleanConversionCheck) {
|
| helper = const CheckedModeHelper('boolConversionCheck');
|
| } else {
|
| - helper = backend.checkedModeHelpers
|
| - .getCheckedModeHelper(type, typeCast: node.isCastTypeCheck);
|
| + helper = _checkedModeHelpers.getCheckedModeHelper(type,
|
| + typeCast: node.isCastTypeCheck);
|
| }
|
|
|
| - push(helper.generateCall(this, node));
|
| + StaticUse staticUse = helper.getStaticUse(_helpers);
|
| + _registry.registerStaticUse(staticUse);
|
| + List<js.Expression> arguments = <js.Expression>[];
|
| + use(node.checkedInput);
|
| + arguments.add(pop());
|
| + helper.generateAdditionalArguments(this, _namer, node, arguments);
|
| + push(new js.Call(
|
| + _emitter.staticFunctionAccess(staticUse.element), arguments));
|
| }
|
|
|
| void visitTypeKnown(HTypeKnown node) {
|
| @@ -2906,7 +2937,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| void visitTypeInfoReadRaw(HTypeInfoReadRaw node) {
|
| use(node.inputs[0]);
|
| js.Expression receiver = pop();
|
| - push(js.js(r'#.#', [receiver, backend.namer.rtiFieldJsName]));
|
| + push(js.js(r'#.#', [receiver, _namer.rtiFieldJsName]));
|
| }
|
|
|
| void visitTypeInfoReadVariable(HTypeInfoReadVariable node) {
|
| @@ -2919,20 +2950,18 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
|
|
| if (typeVariableAccessNeedsSubstitution(element, object.instructionType)) {
|
| js.Expression typeName =
|
| - js.quoteName(backend.namer.runtimeTypeName(element.typeDeclaration));
|
| - FunctionEntity helperElement = helpers.getRuntimeTypeArgument;
|
| - registry.registerStaticUse(
|
| + js.quoteName(_namer.runtimeTypeName(element.typeDeclaration));
|
| + FunctionEntity helperElement = _helpers.getRuntimeTypeArgument;
|
| + _registry.registerStaticUse(
|
| new StaticUse.staticInvoke(helperElement, CallStructure.THREE_ARGS));
|
| - js.Expression helper =
|
| - backend.emitter.staticFunctionAccess(helperElement);
|
| + js.Expression helper = _emitter.staticFunctionAccess(helperElement);
|
| push(js.js(
|
| r'#(#, #, #)', [helper, receiver, typeName, js.js.number(index)]));
|
| } else {
|
| - FunctionEntity helperElement = helpers.getTypeArgumentByIndex;
|
| - registry.registerStaticUse(
|
| + FunctionEntity helperElement = _helpers.getTypeArgumentByIndex;
|
| + _registry.registerStaticUse(
|
| new StaticUse.staticInvoke(helperElement, CallStructure.TWO_ARGS));
|
| - js.Expression helper =
|
| - backend.emitter.staticFunctionAccess(helperElement);
|
| + js.Expression helper = _emitter.staticFunctionAccess(helperElement);
|
| push(js.js(r'#(#, #)', [helper, receiver, js.js.number(index)]));
|
| }
|
| }
|
| @@ -2947,7 +2976,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| switch (node.kind) {
|
| case TypeInfoExpressionKind.COMPLETE:
|
| int index = 0;
|
| - js.Expression result = backend.rtiEncoder.getTypeRepresentation(
|
| + js.Expression result = _rtiEncoder.getTypeRepresentation(
|
| node.dartType, (TypeVariableType variable) => arguments[index++]);
|
| assert(index == node.inputs.length);
|
| push(result);
|
| @@ -2957,7 +2986,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| // We expect only flat types for the INSTANCE representation.
|
| assert((node.dartType as InterfaceType).typeArguments.length ==
|
| arguments.length);
|
| - registry.registerInstantiatedClass(commonElements.listClass);
|
| + _registry.registerInstantiatedClass(_commonElements.listClass);
|
| push(new js.ArrayInitializer(arguments)
|
| .withSourceInformation(node.sourceInformation));
|
| }
|
| @@ -2971,17 +3000,17 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
|
| // indexed.
|
| // TODO(sra): Currently the only convenient query is [singleClass]. We
|
| // should iterate over all the concrete classes in [receiverMask].
|
| - ClassEntity receiverClass = receiverMask.singleClass(closedWorld);
|
| + ClassEntity receiverClass = receiverMask.singleClass(_closedWorld);
|
| if (receiverClass != null) {
|
| - if (backend.rtiSubstitutions.isTrivialSubstitution(receiverClass, cls)) {
|
| + if (_rtiSubstitutions.isTrivialSubstitution(receiverClass, cls)) {
|
| return false;
|
| }
|
| }
|
|
|
| - if (closedWorld.isUsedAsMixin(cls)) return true;
|
| + if (_closedWorld.isUsedAsMixin(cls)) return true;
|
|
|
| - return closedWorld.anyStrictSubclassOf(cls, (ClassEntity subclass) {
|
| - return !backend.rtiSubstitutions.isTrivialSubstitution(subclass, cls);
|
| + return _closedWorld.anyStrictSubclassOf(cls, (ClassEntity subclass) {
|
| + return !_rtiSubstitutions.isTrivialSubstitution(subclass, cls);
|
| });
|
| }
|
|
|
|
|