Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(38)

Unified Diff: pkg/compiler/lib/src/ssa/builder_kernel.dart

Issue 2411793007: Revert "Build CFG for various JS() foreign methods" (Closed)
Patch Set: Redo "Build CFG for various JS() foreign methods" Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/compiler/lib/src/kernel/kernel_visitor.dart ('k') | pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/ssa/builder_kernel.dart
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 4665ee8a0ee8ef4ed4813bb152f1e7ecfd90b810..3b9bb36d1a167226ab52a7fd213bcf04571ce317 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -9,15 +9,19 @@ import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
import '../common/names.dart';
import '../common/tasks.dart' show CompilerTask;
import '../compiler.dart';
+import '../constants/values.dart' show StringConstantValue;
import '../dart_types.dart';
import '../elements/elements.dart';
import '../io/source_information.dart';
+import '../js/js.dart' as js;
import '../js_backend/backend.dart' show JavaScriptBackend;
import '../kernel/kernel.dart';
+import '../native/native.dart' as native;
import '../resolution/tree_elements.dart';
import '../tree/dartstring.dart';
import '../types/masks.dart';
import '../universe/selector.dart';
+import '../universe/side_effects.dart' show SideEffects;
import 'graph_builder.dart';
import 'kernel_ast_adapter.dart';
import 'kernel_string_builder.dart';
@@ -567,12 +571,16 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
@override
void visitStaticGet(ir.StaticGet staticGet) {
- var staticTarget = staticGet.target;
+ ir.Member staticTarget = staticGet.target;
if (staticTarget is ir.Procedure &&
staticTarget.kind == ir.ProcedureKind.Getter) {
// Invoke the getter
_pushStaticInvocation(staticTarget, const <HInstruction>[],
astAdapter.returnTypeOf(staticTarget));
+ } else if (staticTarget is ir.Field && staticTarget.isConst) {
+ assert(staticTarget.initializer != null);
+ stack.add(graph.addConstant(
+ astAdapter.getConstantFor(staticTarget.initializer), compiler));
} else {
Element element = astAdapter.getElement(staticTarget).declaration;
push(new HStatic(element, astAdapter.inferredTypeOf(staticTarget)));
@@ -671,6 +679,10 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
@override
void visitStaticInvocation(ir.StaticInvocation invocation) {
ir.Procedure target = invocation.target;
+ if (astAdapter.isInForeignLibrary(target)) {
+ handleInvokeStaticForeign(invocation, target);
+ return;
+ }
TypeMask typeMask = astAdapter.returnTypeOf(target);
List<HInstruction> arguments = _visitArguments(invocation.arguments);
@@ -678,6 +690,378 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
_pushStaticInvocation(target, arguments, typeMask);
}
+ void handleInvokeStaticForeign(
+ ir.StaticInvocation invocation, ir.Procedure target) {
+ String name = target.name.name;
+ if (name == 'JS') {
+ handleForeignJs(invocation);
+ } else if (name == 'JS_CURRENT_ISOLATE_CONTEXT') {
+ handleForeignJsCurrentIsolateContext(invocation);
+ } else if (name == 'JS_CALL_IN_ISOLATE') {
+ handleForeignJsCallInIsolate(invocation);
+ } else if (name == 'DART_CLOSURE_TO_JS') {
+ handleForeignDartClosureToJs(invocation, 'DART_CLOSURE_TO_JS');
+ } else if (name == 'RAW_DART_FUNCTION_REF') {
+ handleForeignRawFunctionRef(invocation, 'RAW_DART_FUNCTION_REF');
+ } else if (name == 'JS_SET_STATIC_STATE') {
+ handleForeignJsSetStaticState(invocation);
+ } else if (name == 'JS_GET_STATIC_STATE') {
+ handleForeignJsGetStaticState(invocation);
+ } else if (name == 'JS_GET_NAME') {
+ handleForeignJsGetName(invocation);
+ } else if (name == 'JS_EMBEDDED_GLOBAL') {
+ handleForeignJsEmbeddedGlobal(invocation);
+ } else if (name == 'JS_BUILTIN') {
+ handleForeignJsBuiltin(invocation);
+ } else if (name == 'JS_GET_FLAG') {
+ handleForeignJsGetFlag(invocation);
+ } else if (name == 'JS_EFFECT') {
+ stack.add(graph.addConstantNull(compiler));
+ } else if (name == 'JS_INTERCEPTOR_CONSTANT') {
+ handleJsInterceptorConstant(invocation);
+ } else if (name == 'JS_STRING_CONCAT') {
+ handleJsStringConcat(invocation);
+ } else {
+ compiler.reporter.internalError(
+ astAdapter.getNode(invocation), "Unknown foreign: ${name}");
+ }
+ }
+
+ bool _unexpectedForeignArguments(
+ ir.StaticInvocation invocation, int minPositional, [int maxPositional]) {
+
+ String pluralizeArguments(int count) {
+ if (count == 0) return 'no arguments';
+ if (count == 1) return 'one argument';
+ if (count == 2) return 'two arguments';
+ return '$count arguments';
+ }
+ String name() => invocation.target.name.name;
+
+
+ ir.Arguments arguments = invocation.arguments;
+ bool bad = false;
+ if (arguments.types.isNotEmpty) {
+ compiler.reporter.reportErrorMessage(
+ astAdapter.getNode(invocation),
+ MessageKind.GENERIC,
+ {'text': "Error: '${name()}' does not take type arguments."});
+ bad = true;
+ }
+ if (arguments.positional.length < minPositional) {
+ String phrase = pluralizeArguments(minPositional);
+ if (maxPositional != minPositional) phrase = 'at least $phrase';
+ compiler.reporter.reportErrorMessage(
+ astAdapter.getNode(invocation),
+ MessageKind.GENERIC,
+ {'text': "Error: Too few arguments. '${name()}' takes $phrase."});
+ bad = true;
+ }
+ if (maxPositional != null && arguments.positional.length > maxPositional) {
+ String phrase = pluralizeArguments(maxPositional);
+ if (maxPositional != minPositional) phrase = 'at most $phrase';
+ compiler.reporter.reportErrorMessage(
+ astAdapter.getNode(invocation),
+ MessageKind.GENERIC,
+ {'text': "Error: Too many arguments. '${name()}' takes $phrase."});
+ bad = true;
+ }
+ if (arguments.named.isNotEmpty) {
+ compiler.reporter.reportErrorMessage(
+ astAdapter.getNode(invocation),
+ MessageKind.GENERIC,
+ {'text': "Error: '${name()}' does not take named arguments."});
+ bad = true;
+ }
+ return bad;
+ }
+
+ /// Returns the value of the string argument. The argument must evaluate to a
+ /// constant. If there is an error, the error is reported and `null` is
+ /// returned.
+ String _foreignConstantStringArgument(
+ ir.StaticInvocation invocation, int position, String methodName,
+ [String adjective = '']) {
+ ir.Expression argument = invocation.arguments.positional[position];
+ argument.accept(this);
+ HInstruction instruction = pop();
+
+ if (!instruction.isConstantString()) {
+ compiler.reporter.reportErrorMessage(
+ astAdapter.getNode(argument), MessageKind.GENERIC, {
+ 'text': "Error: Expected String constant as ${adjective}argument "
+ "to '$methodName'."
+ });
+ return null;
+ }
+
+ HConstant hConstant = instruction;
+ StringConstantValue stringConstant = hConstant.constant;
+ return stringConstant.primitiveValue.slowToString();
+ }
+
+ // TODO(sra): Remove when handleInvokeStaticForeign fully implemented.
+ void unhandledForeign(ir.StaticInvocation invocation) {
+ ir.Procedure target = invocation.target;
+ TypeMask typeMask = astAdapter.returnTypeOf(target);
+ List<HInstruction> arguments = _visitArguments(invocation.arguments);
+ _pushStaticInvocation(target, arguments, typeMask);
+ }
+
+ void handleForeignJsCurrentIsolateContext(ir.StaticInvocation invocation) {
+ if (_unexpectedForeignArguments(invocation, 0, 0)) {
+ stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+ return;
+ }
+
+ if (!compiler.hasIsolateSupport) {
+ // If the isolate library is not used, we just generate code
+ // to fetch the static state.
+ String name = backend.namer.staticStateHolder;
+ push(new HForeignCode(
+ js.js.parseForeignJS(name), backend.dynamicType, <HInstruction>[],
+ nativeBehavior: native.NativeBehavior.DEPENDS_OTHER));
+ } else {
+ // Call a helper method from the isolate library. The isolate library uses
+ // its own isolate structure that encapsulates the isolate structure used
+ // for binding to methods.
+ ir.Procedure target = astAdapter.currentIsolate;
+ Element element = helpers.currentIsolate;
+ if (target == null) {
+ compiler.reporter.internalError(node, 'Isolate library and compiler mismatch.');
+ }
+ _pushStaticInvocation(target, <HInstruction>[], backend.dynamicType);
+ }
+
+ /*
+ if (!node.arguments.isEmpty) {
+ reporter.internalError(
+ node, 'Too many arguments to JS_CURRENT_ISOLATE_CONTEXT.');
+ }
+
+ if (!compiler.hasIsolateSupport) {
+ // If the isolate library is not used, we just generate code
+ // to fetch the static state.
+ String name = backend.namer.staticStateHolder;
+ push(new HForeignCode(
+ js.js.parseForeignJS(name), backend.dynamicType, <HInstruction>[],
+ nativeBehavior: native.NativeBehavior.DEPENDS_OTHER));
+ } else {
+ // Call a helper method from the isolate library. The isolate
+ // library uses its own isolate structure, that encapsulates
+ // Leg's isolate.
+ Element element = helpers.currentIsolate;
+ if (element == null) {
+ reporter.internalError(node, 'Isolate library and compiler mismatch.');
+ }
+ pushInvokeStatic(null, element, [], typeMask: backend.dynamicType);
+ }
+ */
+ }
+
+ void handleForeignJsCallInIsolate(ir.StaticInvocation invocation) {
+ unhandledForeign(invocation);
+ }
+
+ void handleForeignDartClosureToJs(
+ ir.StaticInvocation invocation, String name) {
+ unhandledForeign(invocation);
+ }
+
+ void handleForeignRawFunctionRef(
+ ir.StaticInvocation invocation, String name) {
+ unhandledForeign(invocation);
+ }
+
+ void handleForeignJsSetStaticState(ir.StaticInvocation invocation) {
+ if (_unexpectedForeignArguments(invocation, 0, 0)) {
+ stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+ return;
+ }
+ _visitArguments(invocation.arguments);
+ String isolateName = backend.namer.staticStateHolder;
+ SideEffects sideEffects = new SideEffects.empty();
+ sideEffects.setAllSideEffects();
+ push(new HForeignCode(js.js.parseForeignJS("$isolateName = #"),
+ backend.dynamicType, <HInstruction>[pop()],
+ nativeBehavior: native.NativeBehavior.CHANGES_OTHER,
+ effects: sideEffects));
+ }
+
+ void handleForeignJsGetStaticState(ir.StaticInvocation invocation) {
+ if (_unexpectedForeignArguments(invocation, 0, 0)) {
+ stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+ return;
+ }
+
+ push(new HForeignCode(js.js.parseForeignJS(backend.namer.staticStateHolder),
+ backend.dynamicType, <HInstruction>[],
+ nativeBehavior: native.NativeBehavior.DEPENDS_OTHER));
+ }
+
+ void handleForeignJsGetName(ir.StaticInvocation invocation) {
+ if (_unexpectedForeignArguments(invocation, 1, 1)) {
+ stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+ return;
+ }
+
+ ir.Node argument = invocation.arguments.positional.first;
+ argument.accept(this);
+ HInstruction instruction = pop();
+
+ if (instruction is HConstant) {
+ js.Name name =
+ astAdapter.getNameForJsGetName(argument, instruction.constant);
+ stack.add(graph.addConstantStringFromName(name, compiler));
+ return;
+ }
+
+ compiler.reporter.reportErrorMessage(
+ astAdapter.getNode(argument),
+ MessageKind.GENERIC,
+ {'text': 'Error: Expected a JsGetName enum value.'});
+ stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+ }
+
+ void handleForeignJsEmbeddedGlobal(ir.StaticInvocation invocation) {
+ if (_unexpectedForeignArguments(invocation, 2, 2)) {
+ stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+ return;
+ }
+ String globalName = _foreignConstantStringArgument(
+ invocation, 1, 'JS_EMBEDDED_GLOBAL', 'second ');
+ js.Template expr = js.js.expressionTemplateYielding(
+ backend.emitter.generateEmbeddedGlobalAccess(globalName));
+
+ native.NativeBehavior nativeBehavior =
+ astAdapter.getNativeBehavior(invocation);
+ assert(invariant(astAdapter.getNode(invocation), nativeBehavior != null,
+ message: "No NativeBehavior for $invocation"));
+
+ TypeMask ssaType = astAdapter.typeFromNativeBehavior(nativeBehavior);
+ push(new HForeignCode(expr, ssaType, const <HInstruction>[],
+ nativeBehavior: nativeBehavior));
+ }
+
+ void handleForeignJsBuiltin(ir.StaticInvocation invocation) {
+ if (_unexpectedForeignArguments(invocation, 2)) {
+ stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+ return;
+ }
+
+ List<ir.Expression> arguments = invocation.arguments.positional;
+ ir.Expression nameArgument = arguments[1];
+
+ nameArgument.accept(this);
+ HInstruction instruction = pop();
+
+ js.Template template;
+ if (instruction is HConstant) {
+ template = astAdapter.getJsBuiltinTemplate(instruction.constant);
+ }
+ if (template == null) {
+ compiler.reporter.reportErrorMessage(
+ astAdapter.getNode(nameArgument),
+ MessageKind.GENERIC,
+ {'text': 'Error: Expected a JsBuiltin enum value.'});
+ stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+ return;
+ }
+
+ List<HInstruction> inputs = <HInstruction>[];
+ for (ir.Expression argument in arguments.skip(2)) {
+ argument.accept(this);
+ inputs.add(pop());
+ }
+
+ native.NativeBehavior nativeBehavior =
+ astAdapter.getNativeBehavior(invocation);
+ assert(invariant(astAdapter.getNode(invocation), nativeBehavior != null,
+ message: "No NativeBehavior for $invocation"));
+
+ TypeMask ssaType = astAdapter.typeFromNativeBehavior(nativeBehavior);
+ push(new HForeignCode(template, ssaType, inputs,
+ nativeBehavior: nativeBehavior));
+ }
+
+ void handleForeignJsGetFlag(ir.StaticInvocation invocation) {
+ if (_unexpectedForeignArguments(invocation, 1, 1)) {
+ stack.add(
+ graph.addConstantBool(false, compiler)); // Result expected on stack.
+ return;
+ }
+ String name = _foreignConstantStringArgument(invocation, 0, 'JS_GET_FLAG');
+ bool value = false;
+ switch (name) {
+ case 'MUST_RETAIN_METADATA':
+ value = backend.mustRetainMetadata;
+ break;
+ case 'USE_CONTENT_SECURITY_POLICY':
+ value = compiler.options.useContentSecurityPolicy;
+ break;
+ default:
+ compiler.reporter.reportErrorMessage(
+ astAdapter.getNode(invocation),
+ MessageKind.GENERIC,
+ {'text': 'Error: Unknown internal flag "$name".'});
+ }
+ stack.add(graph.addConstantBool(value, compiler));
+ }
+
+ void handleJsInterceptorConstant(ir.StaticInvocation invocation) {
+ unhandledForeign(invocation);
+ }
+
+ void handleForeignJs(ir.StaticInvocation invocation) {
+ if (_unexpectedForeignArguments(invocation, 2)) {
+ stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+ return;
+ }
+
+ native.NativeBehavior nativeBehavior =
+ astAdapter.getNativeBehavior(invocation);
+ assert(invariant(astAdapter.getNode(invocation), nativeBehavior != null,
+ message: "No NativeBehavior for $invocation"));
+
+ List<HInstruction> inputs = <HInstruction>[];
+ for (ir.Expression argument in invocation.arguments.positional.skip(2)) {
+ argument.accept(this);
+ inputs.add(pop());
+ }
+
+ if (nativeBehavior.codeTemplate.positionalArgumentCount != inputs.length) {
+ compiler.reporter.reportErrorMessage(
+ astAdapter.getNode(invocation), MessageKind.GENERIC, {
+ 'text': 'Mismatch between number of placeholders'
+ ' and number of arguments.'
+ });
+ stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+ return;
+ }
+
+ if (native.HasCapturedPlaceholders.check(nativeBehavior.codeTemplate.ast)) {
+ compiler.reporter.reportErrorMessage(
+ astAdapter.getNode(invocation), MessageKind.JS_PLACEHOLDER_CAPTURE);
+ }
+
+ TypeMask ssaType = astAdapter.typeFromNativeBehavior(nativeBehavior);
+
+ SourceInformation sourceInformation = null;
+ push(new HForeignCode(nativeBehavior.codeTemplate, ssaType, inputs,
+ isStatement: !nativeBehavior.codeTemplate.isExpression,
+ effects: nativeBehavior.sideEffects,
+ nativeBehavior: nativeBehavior)..sourceInformation = sourceInformation);
+ }
+
+ void handleJsStringConcat(ir.StaticInvocation invocation) {
+ if (_unexpectedForeignArguments(invocation, 2, 2)) {
+ stack.add(graph.addConstantNull(compiler)); // Result expected on stack.
+ return;
+ }
+ List<HInstruction> inputs = _visitArguments(invocation.arguments);
+ push(new HStringConcat(inputs[0], inputs[1], backend.stringType));
+ }
+
void _pushStaticInvocation(
ir.Node target, List<HInstruction> arguments, TypeMask typeMask) {
HInstruction instruction = new HInvokeStatic(
« no previous file with comments | « pkg/compiler/lib/src/kernel/kernel_visitor.dart ('k') | pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698