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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/bailout.dart

Issue 16944004: Change how we deal with manual inlining of argument error and NSM when propagating types. This chan… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 6 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
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 ssa; 5 part of ssa;
6 6
7 class BailoutInfo { 7 class BailoutInfo {
8 int instructionId; 8 int instructionId;
9 int bailoutId; 9 int bailoutId;
10 BailoutInfo(this.instructionId, this.bailoutId); 10 BailoutInfo(this.instructionId, this.bailoutId);
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 && typeGuardWouldBeValuable(user, speculativeType)) { 207 && typeGuardWouldBeValuable(user, speculativeType)) {
208 return true; 208 return true;
209 } 209 }
210 } 210 }
211 211
212 // Insert type guards if the method is likely to be called in a 212 // Insert type guards if the method is likely to be called in a
213 // loop. 213 // loop.
214 return calledInLoop; 214 return calledInLoop;
215 } 215 }
216 216
217 // Returns whether an invocation of [selector] on [receiver] will throw a
218 // [ArgumentError] if the argument is not of the right type.
219 bool willThrowArgumentError(Selector selector,
220 HInstruction receiver,
221 HType speculativeType) {
222 if (receiver != null
223 && (receiver.isInteger() || receiver.isString(compiler))) {
224 return selector.isOperator()
225 && selector.name != const SourceString('==')
226 && (speculativeType.isNumber() && !speculativeType.isInteger());
227 }
228 return false;
229 }
230
231 // Returns whether an invocation of [selector] will throw a
232 // [NoSuchMethodError] if the receiver is not of the type
233 // [speculativeType].
234 bool willThrowNoSuchMethodErrorIfNot(Selector selector,
235 HType speculativeType) {
236 return compiler.world.hasSingleMatch(selector)
237 // In some cases, we want the receiver to be an integer,
238 // but that does not mean we will get a NoSuchMethodError
239 // if it's not: the receiver could be a double.
240 && !speculativeType.isInteger()
241 // We speculate on the [operator==] instruction, but we know it
242 // will never throw a [NoSuchMethodError].
243 && selector.name != const SourceString('==');
244 }
245
246 bool shouldInsertTypeGuard(HInstruction instruction, HType speculativeType) {
247 if (!speculativeType.isUseful()) return false;
248 // If the types agree we don't need to check.
249 if (speculativeType == instruction.instructionType) return false;
250 // If a bailout check is more expensive than doing the actual operation
251 // don't do it either.
252 return typeGuardWouldBeValuable(instruction, speculativeType);
253 }
254
255 HInstruction computeFirstDominatingUserWithSelector( 217 HInstruction computeFirstDominatingUserWithSelector(
256 HInstruction instruction) { 218 HInstruction instruction) {
257 // TODO(ngeoffray): We currently only look at the instruction's 219 // TODO(ngeoffray): We currently only look at the instruction's
258 // block, so that we know it will be executed. We should lift this 220 // block, so that we know it will be executed. We should lift this
259 // limitation. 221 // limitation.
260 222
261 // For a parameter, we look at the first block that contains 223 // For a parameter, we look at the first block that contains
262 // user instructions. 224 // user instructions.
263 HBasicBlock userMustBeInBlock = instruction is HParameterValue 225 HBasicBlock userMustBeInBlock = instruction is HParameterValue
264 ? instruction.block.successors[0] 226 ? instruction.block.successors[0]
(...skipping 11 matching lines...) Expand all
276 } 238 }
277 239
278 /** 240 /**
279 * Tries to insert a type conversion instruction for [instruction] 241 * Tries to insert a type conversion instruction for [instruction]
280 * instead of a type guard if we know an user will throw. Returns 242 * instead of a type guard if we know an user will throw. Returns
281 * whether it succeeded at adding a type conversion instruction. 243 * whether it succeeded at adding a type conversion instruction.
282 */ 244 */
283 bool tryTypeConversion(HInstruction instruction, HType speculativeType) { 245 bool tryTypeConversion(HInstruction instruction, HType speculativeType) {
284 HInstruction firstUser = 246 HInstruction firstUser =
285 computeFirstDominatingUserWithSelector(instruction); 247 computeFirstDominatingUserWithSelector(instruction);
286 if (firstUser == null) return false; 248 if (firstUser is !HInvokeDynamic) return false;
287 249
288 // If we have found a user with a selector, we find out if it 250 // If we have found a user with a selector, we find out if it
289 // will throw [NoSuchMethodError] or [ArgumentError]. 251 // will throw [NoSuchMethodError] or [ArgumentError].
290 Selector selector = firstUser.selector; 252 Selector selector = firstUser.selector;
291 Selector receiverSelectorOnThrow = null; 253 if (!selector.isOperator()) return false;
292 HInstruction receiver = firstUser.getDartReceiver(compiler); 254 HInstruction receiver = firstUser.getDartReceiver(compiler);
293 bool willThrow = false; 255 if (instruction == receiver) {
kasperl 2013/06/14 06:19:08 Add a comment that explains what you're doing here
ngeoffray 2013/06/14 06:58:34 Done.
294 if (receiver == instruction) { 256 return checkReceiver(firstUser);
295 if (willThrowNoSuchMethodErrorIfNot(selector, speculativeType)) { 257 } else if (!selector.isUnaryOperator()
296 receiverSelectorOnThrow = selector; 258 && instruction == firstUser.inputs[2]) {
297 willThrow = true; 259 return checkArgument(firstUser);
298 }
299 // We need to call the actual method in checked mode to get
300 // the right type error.
301 } else if (!compiler.enableTypeAssertions
302 && willThrowArgumentError(selector, receiver, speculativeType)) {
303 willThrow = true;
304 } 260 }
305 261 return false;
306 if (!willThrow) return false;
307
308 HTypeConversion check = new HTypeConversion(
309 null,
310 receiverSelectorOnThrow == null
311 ? HTypeConversion.ARGUMENT_TYPE_CHECK
312 : HTypeConversion.RECEIVER_TYPE_CHECK,
313 speculativeType,
314 instruction,
315 receiverSelectorOnThrow);
316 hasInsertedChecks = true;
317 firstUser.block.addBefore(firstUser, check);
318 instruction.replaceAllUsersDominatedBy(firstUser, check);
319 return true;
320 } 262 }
321 263
322 bool updateType(HInstruction instruction) { 264 bool updateType(HInstruction instruction) {
323 bool hasChanged = super.updateType(instruction); 265 bool hasChanged = super.updateType(instruction);
324 HType speculativeType = savedTypes[instruction]; 266 HType speculativeType = savedTypes[instruction];
325 if (speculativeType == null) return hasChanged; 267 if (speculativeType == null
268 || !speculativeType.isUseful()
269 || speculativeType == instruction.instructionType) {
270 return hasChanged;
271 }
326 272
327 if (shouldInsertTypeGuard(instruction, speculativeType) 273 if (!tryTypeConversion(instruction, speculativeType)
328 && !tryTypeConversion(instruction, speculativeType)) { 274 && typeGuardWouldBeValuable(instruction, speculativeType)) {
329 HInstruction insertionPoint; 275 HInstruction insertionPoint;
330 if (instruction is HPhi) { 276 if (instruction is HPhi) {
331 insertionPoint = instruction.block.first; 277 insertionPoint = instruction.block.first;
332 } else if (instruction is HParameterValue) { 278 } else if (instruction is HParameterValue) {
333 // We insert the type guard at the end of the entry block 279 // We insert the type guard at the end of the entry block
334 // because if a parameter is live, it must be kept in the live 280 // because if a parameter is live, it must be kept in the live
335 // environment. Not doing so would mean we could visit a 281 // environment. Not doing so would mean we could visit a
336 // parameter and remove it from the environment before 282 // parameter and remove it from the environment before
337 // visiting a type guard. 283 // visiting a type guard.
338 insertionPoint = instruction.block.last; 284 insertionPoint = instruction.block.last;
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after
744 hasComplexBailoutTargets = true; 690 hasComplexBailoutTargets = true;
745 } 691 }
746 } else { 692 } else {
747 hasComplexBailoutTargets = true; 693 hasComplexBailoutTargets = true;
748 blocks.forEach((HBasicBlock block) { 694 blocks.forEach((HBasicBlock block) {
749 block.bailoutTargets.add(target); 695 block.bailoutTargets.add(target);
750 }); 696 });
751 } 697 }
752 } 698 }
753 } 699 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698