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

Side by Side Diff: pkg/compiler/lib/src/native/js.dart

Issue 1074043003: Compute default throws behavior from JavaScript. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 8 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/compiler/lib/src/native/behavior.dart ('k') | pkg/compiler/lib/src/ssa/builder.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of native; 5 part of native;
6 6
7 class SideEffectsVisitor extends js.BaseVisitor { 7 class SideEffectsVisitor extends js.BaseVisitor {
8 final SideEffects sideEffects; 8 final SideEffects sideEffects;
9 SideEffectsVisitor(this.sideEffects); 9 SideEffectsVisitor(this.sideEffects);
10 10
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 node.visitChildren(this); 74 node.visitChildren(this);
75 } 75 }
76 76
77 void visitAccess(js.PropertyAccess node) { 77 void visitAccess(js.PropertyAccess node) {
78 sideEffects.setDependsOnIndexStore(); 78 sideEffects.setDependsOnIndexStore();
79 sideEffects.setDependsOnInstancePropertyStore(); 79 sideEffects.setDependsOnInstancePropertyStore();
80 sideEffects.setDependsOnStaticPropertyStore(); 80 sideEffects.setDependsOnStaticPropertyStore();
81 node.visitChildren(this); 81 node.visitChildren(this);
82 } 82 }
83 } 83 }
84
85
86 /// ThrowBehaviorVisitor generates a NativeThrowBehavior describing the
87 /// exception behavior of a JavaScript expression.
88 ///
89 /// The result is semi-conservative, giving reasonable results for many simple
90 /// JS fragments. The non-conservative part is the assumption that binary
91 /// operators are used on 'good' operands that do not force arbirary code to be
92 /// executed via conversions (valueOf() and toString() methods).
93 ///
94 /// In many cases a JS fragment has more precise behavior. In these cases the
95 /// behavior should be described as a property of the JS fragment. For example,
96 /// Object.keys(#) has a TypeError on null / undefined, which can only be known
97 /// in the calling context.
98 ///
99 class ThrowBehaviorVisitor extends js.BaseVisitor<NativeThrowBehavior> {
100
101 ThrowBehaviorVisitor();
102
103 NativeThrowBehavior analyze(js.Node node) {
104 return visit(node);
105 }
106
107 // TODO(sra): Add [sequence] functionality to NativeThrowBehavior.
108 /// Returns the combined behavior of sequential execution of code having
109 /// behavior [first] followed by code having behavior [second].
110 static NativeThrowBehavior sequence(NativeThrowBehavior first,
111 NativeThrowBehavior second) {
112 if (first == NativeThrowBehavior.MUST) return first;
113 if (second == NativeThrowBehavior.MUST) return second;
114 if (second == NativeThrowBehavior.NEVER) return first;
115 if (first == NativeThrowBehavior.NEVER) return second;
116 // Both are one of MAY or MAY_THROW_ONLY_ON_FIRST_ARGUMENT_ACCESS.
117 return NativeThrowBehavior.MAY;
118 }
119
120 // TODO(sra): Add [choice] functionality to NativeThrowBehavior.
121 /// Returns the combined behavior of a choice between two paths with behaviors
122 /// [first] and [second].
123 static NativeThrowBehavior choice(NativeThrowBehavior first,
124 NativeThrowBehavior second) {
125 if (first == second) return first; // Both paths have same behaviour.
126 return NativeThrowBehavior.MAY;
127 }
128
129 NativeThrowBehavior visit(js.Node node) {
130 return node.accept(this);
131 }
132
133 NativeThrowBehavior visitNode(js.Node node) {
134 return NativeThrowBehavior.MAY;
135 }
136
137 NativeThrowBehavior visitLiteral(js.Literal node) {
138 return NativeThrowBehavior.NEVER;
139 }
140
141 NativeThrowBehavior visitInterpolatedExpression(js.InterpolatedNode node) {
142 return NativeThrowBehavior.NEVER;
143 }
144
145 NativeThrowBehavior visitInterpolatedSelector(js.InterpolatedNode node) {
146 return NativeThrowBehavior.NEVER;
147 }
148
149 NativeThrowBehavior visitObjectInitializer(js.ObjectInitializer node) {
150 NativeThrowBehavior result = NativeThrowBehavior.NEVER;
151 for (js.Property property in node.properties) {
152 result = sequence(result, visit(property));
153 }
154 return result;
155 }
156
157 NativeThrowBehavior visitProperty(js.Property node) {
158 return sequence(visit(node.name), visit(node.value));
159 }
160
161 NativeThrowBehavior visitAssignment(js.Assignment node) {
162 // TODO(sra): Can we make "#.p = #" be null(1)?
163 return NativeThrowBehavior.MAY;
164 }
165
166 NativeThrowBehavior visitCall(js.Call node) {
167 return NativeThrowBehavior.MAY;
168 }
169
170 NativeThrowBehavior visitNew(js.New node) {
171 // TODO(sra): `new Array(x)` where `x` is a small number.
172 return NativeThrowBehavior.MAY;
173 }
174
175 NativeThrowBehavior visitBinary(js.Binary node) {
176 NativeThrowBehavior left = visit(node.left);
177 NativeThrowBehavior right = visit(node.right);
178 switch (node.op) {
179 // We make the non-conservative assumption that these operations are not
180 // used in ways that force calling arbitrary code via valueOf or
181 // toString().
182 case "*":
183 case "/":
184 case "%":
185 case "+":
186 case "-":
187 case "<<":
188 case ">>":
189 case ">>>":
190 case "<":
191 case ">":
192 case "<=":
193 case ">=":
194 case "==":
195 case "===":
196 case "!=":
197 case "!==":
198 case "&":
199 case "^":
200 case "|":
201 return sequence(left, right);
202
203 case ',':
204 return sequence(left, right);
205
206 case "&&":
207 case "||":
208 return choice(left, sequence(left, right));
209
210 case "instanceof":
211 case "in":
212 default:
213 return NativeThrowBehavior.MAY;
214 }
215 }
216
217 NativeThrowBehavior visitThrow(js.Throw node) {
218 return NativeThrowBehavior.MUST;
219 }
220
221 NativeThrowBehavior visitPrefix(js.Prefix node) {
222 if (node.op == 'typeof' && node.argument is js.VariableUse)
223 return NativeThrowBehavior.NEVER;
224 NativeThrowBehavior result = visit(node.argument);
225 switch (node.op) {
226 case '!':
227 case '~':
228 case 'void':
229 case 'typeof':
230 return result;
231 default:
232 return NativeThrowBehavior.MAY;
233 }
234 }
235
236 NativeThrowBehavior visitVariableUse(js.VariableUse node) {
237 // We could get a ReferenceError unless the variable is in scope. The AST
238 // could distinguish in-scope and out-of scope references. For JS fragments,
239 // the only use of VariableUse should be for global references. Certain
240 // global names are almost certainly not reference errors, e.g 'Array'.
241 switch (node.name) {
242 case 'Array':
243 case 'Object':
244 return NativeThrowBehavior.NEVER;
245 default:
246 return NativeThrowBehavior.MAY;
247 }
248 }
249
250 NativeThrowBehavior visitAccess(js.PropertyAccess node) {
251 // TODO(sra): We need a representation where the nsm guard behaviour is
252 // maintained when combined with other throwing behaviour.
253 js.Node receiver = node.receiver;
254 NativeThrowBehavior first = visit(receiver);
255 NativeThrowBehavior second = visit(node.selector);
256
257 if (receiver is js.InterpolatedExpression &&
258 receiver.isPositional &&
259 receiver.nameOrPosition == 0) {
260 first = NativeThrowBehavior.MAY_THROW_ONLY_ON_FIRST_ARGUMENT_ACCESS;
261 } else {
262 first = NativeThrowBehavior.MAY;
263 }
264
265 return sequence(first, second);
266 }
267 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/native/behavior.dart ('k') | pkg/compiler/lib/src/ssa/builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698