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

Unified Diff: pkg/compiler/lib/src/native/behavior.dart

Issue 969093002: dart2js: Allow to encode side-effects in the spec-string of JS and similar built-ins. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix another bad type annotation. Created 5 years, 10 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 | « no previous file | pkg/compiler/lib/src/universe/side_effects.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/native/behavior.dart
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index 5cd5c604a5781d66908c40a3325f1adccba1e586..0d3ca8164ba2a0e96429c85ab980e818184910ac 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -60,17 +60,39 @@ class NativeBehavior {
final SideEffects sideEffects = new SideEffects.empty();
/// Processes the type specification string of a call to JS and stores the
- /// result in the [typesReturned] and [typesInstantiated].
+ /// result in the [typesReturned] and [typesInstantiated]. It furthermore
+ /// computes the side effects, and, if given, invokes [setSideEffects] with
+ /// the computed effects. If no side effects are encoded in the [specString]
+ /// the [setSideEffects] method is not invoked.
///
/// Two forms of the string is supported:
/// 1) A single type string of the form 'void', '', 'var' or 'T1|...|Tn'
/// which defines the types returned and for the later form also created by
/// the call to JS.
- /// 2) A sequence of the form '<tag>:<type-string>;' where <tag> is either
- /// 'returns' or 'creates' and where <type-string> is a type string like in
- /// 1). The type string marked by 'returns' defines the types returned and
- /// 'creates' defines the types created by the call to JS. Each tag kind
- /// can only occur once in the sequence.
+ /// 2) A sequence of the form
+ /// '<type-tag>:<type-string>;<effect-tag>:<effect-string>'
+ /// where <type-tag> is either 'returns' or 'creates' and where
+ /// <type-string> is a type string like in 1). The type string marked by
+ /// 'returns' defines the types returned and 'creates' defines the types
+ /// created by the call to JS.
+ ///
+ /// The <effect-tag> is either 'effects' or 'depends' and
+ /// <effect-string> is either 'all', 'none' or a comma-separated list of
+ /// 'no-index', 'no-instance', 'no-static'.
+ ///
+ /// The flag 'all' indicates that the call affects/depends on every
+ /// side-effect. The flag 'none' indicates that the call does not affect
+ /// (resp. depends on) anything.
+ ///
+ /// 'no-index' indicates that the call does *not* do any array index-store
+ /// (for 'effects'), or depends on any value in an array (for 'depends').
+ /// The flag 'no-instance' indicates that the call does not modify (resp.
+ /// depends on) any instance variable. Similarly static variables are
+ /// indicated with 'no-static'. The flags 'effects' and 'depends' must be
+ /// used in unison (either both are present or none is).
+ ///
+ /// Each tag kind (including the 'type-tag's) can only occur once in the
+ /// sequence.
///
/// [specString] is the specification string, [resolveType] resolves named
/// types into type values, [typesReturned] and [typesInstantiated] collects
@@ -82,7 +104,8 @@ class NativeBehavior {
DiagnosticListener listener,
Spannable spannable,
String specString,
- {dynamic resolveType(String typeString),
+ {void setSideEffects(SideEffects newEffects),
+ dynamic resolveType(String typeString),
List typesReturned, List typesInstantiated,
objectType, nullType}) {
@@ -110,10 +133,11 @@ class NativeBehavior {
}
}
+
if (specString.contains(':')) {
- /// Find and remove a substring of the form 'tag:<type-string>;' from
+ /// Find and remove a substring of the form 'tag:<string>;' from
/// [specString].
- String getTypesString(String tag) {
+ String getTagString(String tag) {
String marker = '$tag:';
int startPos = specString.indexOf(marker);
if (startPos == -1) return null;
@@ -126,7 +150,7 @@ class NativeBehavior {
return typeString;
}
- String returns = getTypesString('returns');
+ String returns = getTagString('returns');
if (returns != null) {
resolveTypesString(returns, onVar: () {
typesReturned.add(objectType);
@@ -136,7 +160,7 @@ class NativeBehavior {
});
}
- String creates = getTypesString('creates');
+ String creates = getTagString('creates');
if (creates != null) {
resolveTypesString(creates, onVoid: () {
listener.internalError(spannable,
@@ -149,8 +173,77 @@ class NativeBehavior {
});
}
+ String effects = getTagString('effects');
+ String depends = getTagString('depends');
+ if (effects != null && depends == null ||
+ effects == null && depends != null) {
+ listener.internalError(spannable,
+ "Invalid JS spec string. "
+ "'effects' and 'depends' must occur together.");
+ }
+
+ if (effects != null) {
+ SideEffects sideEffects = new SideEffects();
+ if (effects == "none") {
+ sideEffects.clearAllSideEffects();
+ } else if (effects == "all") {
+ // Don't do anything.
+ } else {
+ List<String> splitEffects = effects.split(",");
+ if (splitEffects.isEmpty) {
+ listener.internalError(spannable, "Missing side-effect flag.");
+ }
+ for (String effect in splitEffects) {
+ switch (effect) {
+ case "no-index":
+ sideEffects.clearChangesIndex();
+ break;
+ case "no-instance":
+ sideEffects.clearChangesInstanceProperty();
+ break;
+ case "no-static":
+ sideEffects.clearChangesStaticProperty();
+ break;
+ default:
+ listener.internalError(spannable,
+ "Unrecognized side-effect flag: $effect.");
+ }
+ }
+ }
+
+ if (depends == "none") {
+ sideEffects.clearAllDependencies();
+ } else if (depends == "all") {
+ // Don't do anything.
+ } else {
+ List<String> splitDependencies = depends.split(",");
+ if (splitDependencies.isEmpty) {
+ listener.internalError(spannable,
+ "Missing side-effect dependency flag.");
+ }
+ for (String dependency in splitDependencies) {
+ switch (dependency) {
+ case "no-index":
+ sideEffects.clearDependsOnIndexStore();
+ break;
+ case "no-instance":
+ sideEffects.clearDependsOnInstancePropertyStore();
+ break;
+ case "no-static":
+ sideEffects.clearDependsOnStaticPropertyStore();
+ break;
+ default:
+ listener.internalError(spannable,
+ "Unrecognized side-effect flag: $dependency.");
+ }
+ }
+ }
+
+ setSideEffects(sideEffects);
+ }
+
if (!specString.isEmpty) {
- listener.internalError(spannable, "Invalid JS type string.");
+ listener.internalError(spannable, "Invalid JS spec string.");
}
} else {
resolveTypesString(specString, onVar: () {
@@ -190,12 +283,10 @@ class NativeBehavior {
NativeBehavior behavior = new NativeBehavior();
behavior.codeTemplate =
js.js.parseForeignJS(code.dartString.slowToString());
- new SideEffectsVisitor(behavior.sideEffects)
- .visit(behavior.codeTemplate.ast);
String specString = specLiteral.dartString.slowToString();
- resolveType(String typeString) {
+ dynamic resolveType(String typeString) {
return _parseType(
typeString,
compiler,
@@ -203,14 +294,27 @@ class NativeBehavior {
jsCall);
}
+ bool sideEffectsAreEncodedInSpecString = false;
+
+ void setSideEffects(SideEffects newEffects) {
+ sideEffectsAreEncodedInSpecString = true;
+ behavior.sideEffects.setTo(newEffects);
+ }
+
processSpecString(compiler, jsCall,
specString,
+ setSideEffects: setSideEffects,
resolveType: resolveType,
typesReturned: behavior.typesReturned,
typesInstantiated: behavior.typesInstantiated,
objectType: compiler.objectClass.computeType(compiler),
nullType: compiler.nullClass.computeType(compiler));
+ if (!sideEffectsAreEncodedInSpecString) {
+ new SideEffectsVisitor(behavior.sideEffects)
+ .visit(behavior.codeTemplate.ast);
+ }
+
return behavior;
}
@@ -251,7 +355,7 @@ class NativeBehavior {
String specString = specLiteral.dartString.slowToString();
- resolveType(String typeString) {
+ dynamic resolveType(String typeString) {
return _parseType(
typeString,
compiler,
@@ -259,8 +363,15 @@ class NativeBehavior {
jsGlobalCall);
}
+ void setSideEffects(SideEffects newEffects) {
+ compiler.internalError(jsGlobalCall,
+ 'Embedded global calls may not have any side-effect overwrites: '
+ '$specString');
+ }
+
processSpecString(compiler, jsGlobalCall,
specString,
+ setSideEffects: setSideEffects,
resolveType: resolveType,
typesReturned: behavior.typesReturned,
typesInstantiated: behavior.typesInstantiated,
@@ -404,13 +515,13 @@ class NativeBehavior {
}
}
- static _parseType(String typeString, Compiler compiler,
+ static dynamic _parseType(String typeString, Compiler compiler,
lookup(name), locationNodeOrElement) {
if (typeString == '=Object') return SpecialType.JsObject;
if (typeString == 'dynamic') {
return const DynamicType();
}
- DartType type = lookup(typeString);
+ var type = lookup(typeString);
if (type != null) return type;
int index = typeString.indexOf('<');
@@ -427,6 +538,7 @@ class NativeBehavior {
compiler.internalError(
_errorNode(locationNodeOrElement, compiler),
"Type '$typeString' not found.");
+ return null;
}
static _errorNode(locationNodeOrElement, compiler) {
« no previous file with comments | « no previous file | pkg/compiler/lib/src/universe/side_effects.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698