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

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
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/implementation/ssa/codegen.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) 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]. If it does,
252 // then we change just add a [HTypeConversion] instruction and
253 // avoid a bailout.
290 Selector selector = firstUser.selector; 254 Selector selector = firstUser.selector;
291 Selector receiverSelectorOnThrow = null; 255 if (!selector.isOperator()) return false;
292 HInstruction receiver = firstUser.getDartReceiver(compiler); 256 HInstruction receiver = firstUser.getDartReceiver(compiler);
293 bool willThrow = false; 257
294 if (receiver == instruction) { 258 if (instruction == receiver) {
295 if (willThrowNoSuchMethodErrorIfNot(selector, speculativeType)) { 259 // If the instruction on which we're speculating the
296 receiverSelectorOnThrow = selector; 260 // type is the receiver of the call, check if it will throw
297 willThrow = true; 261 // [NoSuchMethodError] if [instruction] is not of the speculated
298 } 262 // type.
299 // We need to call the actual method in checked mode to get 263 return checkReceiver(firstUser);
300 // the right type error. 264 } else if (!selector.isUnaryOperator()
301 } else if (!compiler.enableTypeAssertions 265 && instruction == firstUser.inputs[2]) {
302 && willThrowArgumentError(selector, receiver, speculativeType)) { 266 // If the instruction is a parameter of the call, we check if
303 willThrow = true; 267 // the method will throw an [ArgumentError] if [instruction] is
268 // not of the speculated type.
269 return checkArgument(firstUser);
304 } 270 }
305 271 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 } 272 }
321 273
322 bool updateType(HInstruction instruction) { 274 bool updateType(HInstruction instruction) {
323 bool hasChanged = super.updateType(instruction); 275 bool hasChanged = super.updateType(instruction);
324 HType speculativeType = savedTypes[instruction]; 276 HType speculativeType = savedTypes[instruction];
325 if (speculativeType == null) return hasChanged; 277 if (speculativeType == null
278 || !speculativeType.isUseful()
279 || speculativeType == instruction.instructionType) {
280 return hasChanged;
281 }
326 282
327 if (shouldInsertTypeGuard(instruction, speculativeType) 283 if (!tryTypeConversion(instruction, speculativeType)
328 && !tryTypeConversion(instruction, speculativeType)) { 284 && typeGuardWouldBeValuable(instruction, speculativeType)) {
329 HInstruction insertionPoint; 285 HInstruction insertionPoint;
330 if (instruction is HPhi) { 286 if (instruction is HPhi) {
331 insertionPoint = instruction.block.first; 287 insertionPoint = instruction.block.first;
332 } else if (instruction is HParameterValue) { 288 } else if (instruction is HParameterValue) {
333 // We insert the type guard at the end of the entry block 289 // 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 290 // because if a parameter is live, it must be kept in the live
335 // environment. Not doing so would mean we could visit a 291 // environment. Not doing so would mean we could visit a
336 // parameter and remove it from the environment before 292 // parameter and remove it from the environment before
337 // visiting a type guard. 293 // visiting a type guard.
338 insertionPoint = instruction.block.last; 294 insertionPoint = instruction.block.last;
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after
744 hasComplexBailoutTargets = true; 700 hasComplexBailoutTargets = true;
745 } 701 }
746 } else { 702 } else {
747 hasComplexBailoutTargets = true; 703 hasComplexBailoutTargets = true;
748 blocks.forEach((HBasicBlock block) { 704 blocks.forEach((HBasicBlock block) {
749 block.bailoutTargets.add(target); 705 block.bailoutTargets.add(target);
750 }); 706 });
751 } 707 }
752 } 708 }
753 } 709 }
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/implementation/ssa/codegen.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698