Skip to content

Commit

Permalink
Revert "cps-ir: Support foreign code."
Browse files Browse the repository at this point in the history
This reverts commit a120ee7.

TBR=kmillikin@google.com

Review URL: https://codereview.chromium.org//1196443002.
  • Loading branch information
karlklose committed Jun 18, 2015
1 parent a120ee7 commit 40ed0da
Show file tree
Hide file tree
Showing 30 changed files with 604 additions and 4,653 deletions.
25 changes: 0 additions & 25 deletions pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ import 'cps_ir_nodes.dart' as ir;
import 'cps_ir_builder_task.dart' show DartCapturedVariables,
GlobalProgramInformation;

import '../common.dart' as types show TypeMask;
import '../js/js.dart' as js show Template;
import '../native/native.dart' show NativeBehavior;

/// A mapping from variable elements to their compile-time values.
///
/// Map elements denoted by parameters and local variables to the
Expand Down Expand Up @@ -2415,27 +2411,6 @@ class JsIrBuilder extends IrBuilder {
return addPrimitive(new ir.CreateInvocationMirror(selector, arguments));
}

ir.Primitive buildForeignCode(js.Template codeTemplate,
List<ir.Primitive> arguments,
NativeBehavior behavior,
{Element dependency}) {
types.TypeMask type = program.getTypeMaskForForeign(behavior);
if (codeTemplate.isExpression) {
return _continueWithExpression((k) => new ir.ForeignCode(
codeTemplate,
type,
arguments,
behavior,
continuation: k,
dependency: dependency));
} else {
assert(isOpen);
add(new ir.ForeignCode(codeTemplate, type, arguments, behavior,
dependency: dependency));
_current = null;
}
}

@override
ir.Primitive buildTypeOperator(ir.Primitive value,
DartType type,
Expand Down
253 changes: 10 additions & 243 deletions pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,6 @@ import '../types/types.dart' show TypeMask;
import '../universe/universe.dart' show SelectorKind, CallStructure;
import 'cps_ir_nodes.dart' as ir;
import 'cps_ir_builder.dart';
import '../native/native.dart' show NativeBehavior;

// TODO(karlklose): remove.
import '../js/js.dart' as js show js, Template, Expression;
import '../ssa/ssa.dart' show TypeMaskFactory;
import '../types/types.dart' show TypeMask;
import '../util/util.dart';

import 'package:_internal/compiler/js_lib/shared/embedded_names.dart'
show JsBuiltin, JsGetName;
import '../constants/values.dart';

typedef void IrBuilderCallback(Element element, ir.FunctionDefinition irNode);

Expand Down Expand Up @@ -995,7 +984,15 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
MethodElement function,
ast.NodeList arguments,
CallStructure callStructure,
_);
_) {
// TODO(karlklose): support foreign functions.
if (compiler.backend.isForeign(function)) {
return giveup(node, 'handleStaticFunctionInvoke: foreign: $function');
}
return irBuilder.buildStaticFunctionInvocation(function, callStructure,
translateStaticArguments(arguments, function, callStructure),
sourceInformation: sourceInformationBuilder.buildCall(node));
}

@override
ir.Primitive handleStaticFunctionIncompatibleInvoke(
Expand Down Expand Up @@ -1886,7 +1883,7 @@ abstract class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
}
}

internalError(ast.Node node, String message) {
void internalError(ast.Node node, String message) {
giveup(node, message);
}

Expand Down Expand Up @@ -2081,10 +2078,6 @@ class GlobalProgramInformation {
ClassElement get nullClass => _compiler.nullClass;

DartType unaliasType(DartType type) => type.unalias(_compiler);

TypeMask getTypeMaskForForeign(NativeBehavior behavior) {
return TypeMaskFactory.fromNativeBehavior(behavior, _compiler);
}
}

/// IR builder specific to the JavaScript backend, coupled to the [JsIrBuilder].
Expand Down Expand Up @@ -2838,232 +2831,6 @@ class JsIrBuilderVisitor extends IrBuilderVisitor {
return irBuilder.buildStaticFieldGet(field, src);
}
}

/// Build code to handle foreign code, that is, native JavaScript code, or
/// builtin values and operations of the backend.
ir.Primitive handleForeignCode(ast.Send node,
MethodElement function,
ast.NodeList argumentList,
CallStructure callStructure) {

void validateArgumentCount({int minimum, int exactly}) {
assert((minimum == null) != (exactly == null));
int count = 0;
int maximum;
if (exactly != null) {
minimum = exactly;
maximum = exactly;
}
for (ast.Node argument in argumentList) {
count++;
if (maximum != null && count > maximum) {
internalError(argument, 'Additional argument.');
}
}
if (count < minimum) {
internalError(node, 'Expected at least $minimum arguments.');
}
}

/// Call a helper method from the isolate library. The isolate library uses
/// its own isolate structure, that encapsulates dart2js's isolate.
ir.Primitive buildIsolateHelperInvocation(String helperName,
CallStructure callStructure) {
Element element = backend.isolateHelperLibrary.find(helperName);
if (element == null) {
compiler.internalError(node,
'Isolate library and compiler mismatch.');
}
List<ir.Primitive> arguments = translateStaticArguments(argumentList,
element, CallStructure.TWO_ARGS);
return irBuilder.buildStaticFunctionInvocation(element,
CallStructure.TWO_ARGS, arguments,
sourceInformation: sourceInformationBuilder.buildCall(node));
}

/// Lookup the value of the enum described by [node].
getEnumValue(ast.Node node, EnumClassElement enumClass, List values) {
Element element = elements[node];
if (element is! FieldElement || element.enclosingClass != enumClass) {
internalError(node, 'expected a JsBuiltin enum value');
}

int index = enumClass.enumValues.indexOf(element);
return values[index];
}

/// Returns the String the node evaluates to, or throws an error if the
/// result is not a string constant.
String expectStringConstant(ast.Node node) {
ir.Primitive nameValue = visit(node);
if (nameValue is ir.Constant && nameValue.value.isString) {
StringConstantValue constantValue = nameValue.value;
return constantValue.primitiveValue.slowToString();
} else {
return internalError(node, 'expected a literal string');
}
}

Link<ast.Node> argumentNodes = argumentList.nodes;
NativeBehavior behavior =
compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node);
switch (function.name) {
case 'JS':
validateArgumentCount(minimum: 2);
// The first two arguments are the type and the foreign code template,
// which already have been analyzed by the resolver and can be retrieved
// using [NativeBehavior]. We can ignore these arguments in the backend.
List<ir.Primitive> arguments =
argumentNodes.skip(2).mapToList(visit, growable: false);
return irBuilder.buildForeignCode(behavior.codeTemplate, arguments,
behavior);

case 'DART_CLOSURE_TO_JS':
// TODO(ahe): This should probably take care to wrap the closure in
// another closure that saves the current isolate.
case 'RAW_DART_FUNCTION_REF':
validateArgumentCount(exactly: 1);

ast.Node argument = node.arguments.single;
FunctionElement closure = elements[argument].implementation;
if (!Elements.isStaticOrTopLevelFunction(closure)) {
internalError(argument,
'only static or toplevel function supported');
}
if (closure.functionSignature.hasOptionalParameters) {
internalError(argument,
'closures with optional parameters not supported');
}
return irBuilder.buildForeignCode(
js.js.expressionTemplateYielding(
backend.emitter.staticFunctionAccess(function)),
<ir.Primitive>[],
NativeBehavior.PURE,
dependency: closure);

case 'JS_BUILTIN':
// The first argument is a description of the type and effect of the
// builtin, which has already been analyzed in the frontend. The second
// argument must be a [JsBuiltin] value. All other arguments are
// values used by the JavaScript template that is associated with the
// builtin.
validateArgumentCount(minimum: 2);

ast.Node builtin = argumentNodes.tail.head;
JsBuiltin value = getEnumValue(argumentNodes.tail.head,
backend.jsBuiltinEnum, JsBuiltin.values);
js.Template template = backend.emitter.builtinTemplateFor(value);
List<ir.Primitive> arguments =
argumentNodes.skip(2).mapToList(visit, growable: false);
return irBuilder.buildForeignCode(template, arguments, behavior);

case 'JS_EMBEDDED_GLOBAL':
validateArgumentCount(exactly: 2);

String name = expectStringConstant(argumentNodes.tail.head);
js.Expression access =
backend.emitter.generateEmbeddedGlobalAccess(name);
js.Template template = js.js.expressionTemplateYielding(access);
return irBuilder.buildForeignCode(template, <ir.Primitive>[], behavior);

case 'JS_INTERCEPTOR_CONSTANT':
validateArgumentCount(exactly: 1);

ast.Node argument = argumentNodes.head;
ir.Primitive argumentValue = visit(argument);
if (argumentValue is ir.Constant && argumentValue.value.isType) {
TypeConstantValue constant = argumentValue.value;
ConstantValue interceptorValue =
new InterceptorConstantValue(constant.representedType);
return irBuilder.buildConstant(argumentValue.expression,
interceptorValue);
} else {
internalError(argument, 'expected Type as argument');
}
break;

case 'JS_EFFECT':
return irBuilder.buildNullConstant();

case 'JS_GET_NAME':
validateArgumentCount(exactly: 1);

ast.Node argument = argumentNodes.head;
JsGetName id = getEnumValue(argument, backend.jsGetNameEnum,
JsGetName.values);
String name = backend.namer.getNameForJsGetName(argument, id);
return irBuilder.buildStringConstant(name);

case 'JS_GET_FLAG':
validateArgumentCount(exactly: 1);

String name = expectStringConstant(argumentNodes.first);
bool value = false;
switch (name) {
case 'MUST_RETAIN_METADATA':
value = backend.mustRetainMetadata;
break;
case 'USE_CONTENT_SECURITY_POLICY':
value = compiler.useContentSecurityPolicy;
break;
default:
internalError(node, 'Unknown internal flag "$name".');
}
return irBuilder.buildBooleanConstant(value);

case 'JS_STRING_CONCAT':
validateArgumentCount(exactly: 2);
List<ir.Primitive> arguments = argumentNodes.mapToList(visit);
return irBuilder.buildStringConcatenation(arguments);

case 'JS_CURRENT_ISOLATE_CONTEXT':
validateArgumentCount(exactly: 0);

if (!compiler.hasIsolateSupport) {
// If the isolate library is not used, we just generate code
// to fetch the current isolate.
String name = backend.namer.currentIsolate;
return irBuilder.buildForeignCode(js.js.parseForeignJS(name),
const <ir.Primitive>[], NativeBehavior.PURE);
} else {
return buildIsolateHelperInvocation('_currentIsolate',
CallStructure.NO_ARGS);
}
break;

case 'JS_CALL_IN_ISOLATE':
validateArgumentCount(exactly: 2);

if (!compiler.hasIsolateSupport) {
ir.Primitive closure = visit(argumentNodes.tail.head);
return irBuilder.buildCallInvocation(closure, CallStructure.NO_ARGS,
const <ir.Primitive>[]);
} else {
return buildIsolateHelperInvocation('_callInIsolate',
CallStructure.TWO_ARGS);
}
break;

default:
giveup(node, 'unplemented native construct: ${function.name}');
break;
}
}

@override
ir.Primitive handleStaticFunctionInvoke(ast.Send node,
MethodElement function,
ast.NodeList argumentList,
CallStructure callStructure,
_) {
if (compiler.backend.isForeign(function)) {
return handleForeignCode(node, function, argumentList, callStructure);
} else {
return irBuilder.buildStaticFunctionInvocation(function, callStructure,
translateStaticArguments(argumentList, function, callStructure),
sourceInformation: sourceInformationBuilder.buildCall(node));
}
}
}

/// Perform simple post-processing on the initial CPS-translated root term.
Expand Down
37 changes: 0 additions & 37 deletions pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,6 @@ import '../universe/universe.dart' show Selector, SelectorKind;
import 'builtin_operator.dart';
export 'builtin_operator.dart';

// These imports are only used for the JavaScript specific nodes. If we want to
// support more than one native backend, we should probably create better
// abstractions for native code and its type and effect system.
import '../js/js.dart' as js show Template;
import '../native/native.dart' as native show NativeBehavior;
import '../types/types.dart' as types show TypeMask;

abstract class Node {
/// A pointer to the parent node. Is null until set by optimization passes.
Node parent;
Expand Down Expand Up @@ -736,26 +729,6 @@ class CreateInvocationMirror extends Primitive {
accept(Visitor visitor) => visitor.visitCreateInvocationMirror(this);
}

class ForeignCode extends Expression {
final js.Template codeTemplate;
final types.TypeMask type;
final List<Reference<Primitive>> arguments;
final native.NativeBehavior nativeBehavior;
final FunctionElement dependency;

/// The continuation, if the foreign code is not a JavaScript 'throw',
/// otherwise null.
final Reference<Continuation> continuation;

ForeignCode(this.codeTemplate, this.type, List<Primitive> arguments,
this.nativeBehavior, {Continuation continuation, this.dependency})
: arguments = _referenceList(arguments),
continuation = continuation == null ? null
: new Reference<Continuation>(continuation);

accept(Visitor visitor) => visitor.visitForeignCode(this);
}

class Constant extends Primitive {
final ConstantExpression expression;
final values.ConstantValue value;
Expand Down Expand Up @@ -990,9 +963,6 @@ abstract class Visitor<T> {

// Conditions.
T visitIsTrue(IsTrue node);

// Support for literal foreign code.
T visitForeignCode(ForeignCode node);
}

/// Recursively visits the entire CPS term, and calls abstract `process*`
Expand Down Expand Up @@ -1278,13 +1248,6 @@ class RecursiveVisitor implements Visitor {
node.arguments.forEach(processReference);
}

processForeignCode(ForeignCode node) {}
visitForeignCode(ForeignCode node) {
processForeignCode(node);
processReference(node.continuation);
node.arguments.forEach(processReference);
}

processUnreachable(Unreachable node) {}
visitUnreachable(Unreachable node) {
processUnreachable(node);
Expand Down
Loading

0 comments on commit 40ed0da

Please sign in to comment.