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

Side by Side Diff: pkg/compiler/lib/src/ssa/optimize.dart

Issue 1459273002: dart2js load elimination: Look through refinements for locations (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 4 years, 3 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
« no previous file with comments | « no previous file | tests/compiler/dart2js_native/load_elim_refinement_test.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 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; 5 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
6 import '../common/tasks.dart' show CompilerTask; 6 import '../common/tasks.dart' show CompilerTask;
7 import '../compiler.dart' show Compiler; 7 import '../compiler.dart' show Compiler;
8 import '../constants/constant_system.dart'; 8 import '../constants/constant_system.dart';
9 import '../constants/values.dart'; 9 import '../constants/values.dart';
10 import '../core_types.dart' show CoreClasses; 10 import '../core_types.dart' show CoreClasses;
(...skipping 2225 matching lines...) Expand 10 before | Expand all | Expand 10 after
2236 if (instruction.usedBy.length != 1) return true; 2236 if (instruction.usedBy.length != 1) return true;
2237 HInstruction use = instruction.usedBy.single; 2237 HInstruction use = instruction.usedBy.single;
2238 // When the only use is an allocation, the allocation becomes the only 2238 // When the only use is an allocation, the allocation becomes the only
2239 // heap alias for the current instruction. 2239 // heap alias for the current instruction.
2240 if (use is HCreate) return interestingUse(use, heapDepth + 1); 2240 if (use is HCreate) return interestingUse(use, heapDepth + 1);
2241 if (use is HLiteralList) return interestingUse(use, heapDepth + 1); 2241 if (use is HLiteralList) return interestingUse(use, heapDepth + 1);
2242 if (use is HInvokeStatic) { 2242 if (use is HInvokeStatic) {
2243 // Assume the argument escapes. All we do with our initial allocation is 2243 // Assume the argument escapes. All we do with our initial allocation is
2244 // have it escape or store it into an object that escapes. 2244 // have it escape or store it into an object that escapes.
2245 return false; 2245 return false;
2246 // TODO(sra): Handle more functions. `setRuntimeTypeInfo` does not 2246 // TODO(sra): Handle library functions that we know do not modify or
2247 // actually kill it's input, but we don't make use of that elsewhere so 2247 // leak the inputs. For example `setRuntimeTypeInfo` is used to mark
2248 // there is not point in checking here. 2248 // list literals with type information.
2249 } 2249 }
2250 if (use is HPhi) { 2250 if (use is HPhi) {
2251 // The initial allocation (it's only alias) gets merged out of the model 2251 // The initial allocation (it's only alias) gets merged out of the model
2252 // of the heap before load. 2252 // of the heap before load.
2253 return false; 2253 return false;
2254 } 2254 }
2255 return true; 2255 return true;
2256 } 2256 }
2257 2257
2258 return interestingUse(instruction, 0); 2258 return interestingUse(instruction, 0);
(...skipping 25 matching lines...) Expand all
2284 } 2284 }
2285 2285
2286 void visitStaticStore(HStaticStore instruction) { 2286 void visitStaticStore(HStaticStore instruction) {
2287 memorySet.registerFieldValueUpdate( 2287 memorySet.registerFieldValueUpdate(
2288 instruction.element, null, instruction.inputs.last); 2288 instruction.element, null, instruction.inputs.last);
2289 } 2289 }
2290 2290
2291 void visitLiteralList(HLiteralList instruction) { 2291 void visitLiteralList(HLiteralList instruction) {
2292 memorySet.registerAllocation(instruction); 2292 memorySet.registerAllocation(instruction);
2293 memorySet.killAffectedBy(instruction); 2293 memorySet.killAffectedBy(instruction);
2294 // TODO(sra): Set initial keyed values.
2295 // TODO(sra): Set initial length.
2294 } 2296 }
2295 2297
2296 void visitIndex(HIndex instruction) { 2298 void visitIndex(HIndex instruction) {
2297 HInstruction receiver = instruction.receiver.nonCheck(); 2299 HInstruction receiver = instruction.receiver.nonCheck();
2298 HInstruction existing = 2300 HInstruction existing =
2299 memorySet.lookupKeyedValue(receiver, instruction.index); 2301 memorySet.lookupKeyedValue(receiver, instruction.index);
2300 if (existing != null) { 2302 if (existing != null) {
2301 instruction.block.rewriteWithBetterUser(instruction, existing); 2303 instruction.block.rewriteWithBetterUser(instruction, existing);
2302 instruction.block.remove(instruction); 2304 instruction.block.remove(instruction);
2303 } else { 2305 } else {
2304 memorySet.registerKeyedValue(receiver, instruction.index, instruction); 2306 memorySet.registerKeyedValue(receiver, instruction.index, instruction);
2305 } 2307 }
2306 } 2308 }
2307 2309
2308 void visitIndexAssign(HIndexAssign instruction) { 2310 void visitIndexAssign(HIndexAssign instruction) {
2309 HInstruction receiver = instruction.receiver.nonCheck(); 2311 HInstruction receiver = instruction.receiver.nonCheck();
2310 memorySet.registerKeyedValueUpdate( 2312 memorySet.registerKeyedValueUpdate(
2311 receiver, instruction.index, instruction.value); 2313 receiver, instruction.index, instruction.value);
2312 } 2314 }
2315
2316 // Pure operations that do not escape their inputs.
2317 void visitBinaryArithmetic(HBinaryArithmetic instruction) {}
2318 void visitConstant(HConstant instruction) {}
2319 void visitIf(HIf instruction) {}
2320 void visitInterceptor(HInterceptor instruction) {}
2321 void visitIs(HIs instruction) {}
2322 void visitIsViaInterceptor(HIsViaInterceptor instruction) {}
2323 void visitNot(HNot instruction) {}
2324 void visitParameterValue(HParameterValue instruction) {}
2325 void visitRelational(HRelational instruction) {}
2326 void visitStringConcat(HStringConcat instruction) {}
2327 void visitTypeKnown(HTypeKnown instruction) {}
2328 void visitTypeInfoReadRaw(HTypeInfoReadRaw instruction) {}
2329 void visitTypeInfoReadVariable(HTypeInfoReadVariable instruction) {}
2330 void visitTypeInfoExpression(HTypeInfoExpression instruction) {}
2313 } 2331 }
2314 2332
2315 /** 2333 /**
2316 * Holds values of memory places. 2334 * Holds values of memory places.
2335 *
2336 * Generally, values that name a place (a receiver) have type refinements and
2337 * other checks removed to ensure that checks and type refinements do not
2338 * confuse aliasing. Values stored into a memory place keep the type
2339 * refinements to help further optimizations.
2317 */ 2340 */
2318 class MemorySet { 2341 class MemorySet {
2319 final Compiler compiler; 2342 final Compiler compiler;
2320 2343
2321 /** 2344 /**
2322 * Maps a field to a map of receiver to value. 2345 * Maps a field to a map of receiver to value.
2323 */ 2346 */
2324 final Map<Element, Map<HInstruction, HInstruction>> fieldValues = 2347 final Map<Element, Map<HInstruction, HInstruction>> fieldValues =
2325 <Element, Map<HInstruction, HInstruction>>{}; 2348 <Element, Map<HInstruction, HInstruction>>{};
2326 2349
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
2372 2395
2373 bool couldBeTypedArray(HInstruction receiver) { 2396 bool couldBeTypedArray(HInstruction receiver) {
2374 JavaScriptBackend backend = compiler.backend; 2397 JavaScriptBackend backend = compiler.backend;
2375 return backend.couldBeTypedArray(receiver.instructionType); 2398 return backend.couldBeTypedArray(receiver.instructionType);
2376 } 2399 }
2377 2400
2378 /** 2401 /**
2379 * Returns whether [receiver] escapes the current function. 2402 * Returns whether [receiver] escapes the current function.
2380 */ 2403 */
2381 bool escapes(HInstruction receiver) { 2404 bool escapes(HInstruction receiver) {
2405 assert(receiver == null || receiver == receiver.nonCheck());
2382 return !nonEscapingReceivers.contains(receiver); 2406 return !nonEscapingReceivers.contains(receiver);
2383 } 2407 }
2384 2408
2385 void registerAllocation(HInstruction instruction) { 2409 void registerAllocation(HInstruction instruction) {
2410 assert(instruction == instruction.nonCheck());
2386 nonEscapingReceivers.add(instruction); 2411 nonEscapingReceivers.add(instruction);
2387 } 2412 }
2388 2413
2389 /** 2414 /**
2390 * Sets `receiver.element` to contain [value]. Kills all potential 2415 * Sets `receiver.element` to contain [value]. Kills all potential places that
2391 * places that may be affected by this update. 2416 * may be affected by this update.
2392 */ 2417 */
2393 void registerFieldValueUpdate( 2418 void registerFieldValueUpdate(
2394 Element element, HInstruction receiver, HInstruction value) { 2419 Element element, HInstruction receiver, HInstruction value) {
2420 assert(receiver == null || receiver == receiver.nonCheck());
2395 if (backend.isNative(element)) { 2421 if (backend.isNative(element)) {
2396 return; // TODO(14955): Remove this restriction? 2422 return; // TODO(14955): Remove this restriction?
2397 } 2423 }
2398 // [value] is being set in some place in memory, we remove it from 2424 // [value] is being set in some place in memory, we remove it from
2399 // the non-escaping set. 2425 // the non-escaping set.
2400 nonEscapingReceivers.remove(value); 2426 nonEscapingReceivers.remove(value.nonCheck());
2401 Map<HInstruction, HInstruction> map = 2427 Map<HInstruction, HInstruction> map =
2402 fieldValues.putIfAbsent(element, () => <HInstruction, HInstruction>{}); 2428 fieldValues.putIfAbsent(element, () => <HInstruction, HInstruction>{});
2403 map.forEach((key, value) { 2429 map.forEach((key, value) {
2404 if (mayAlias(receiver, key)) map[key] = null; 2430 if (mayAlias(receiver, key)) map[key] = null;
2405 }); 2431 });
2406 map[receiver] = value; 2432 map[receiver] = value;
2407 } 2433 }
2408 2434
2409 /** 2435 /**
2410 * Registers that `receiver.element` is now [value]. 2436 * Registers that `receiver.element` is now [value].
2411 */ 2437 */
2412 void registerFieldValue( 2438 void registerFieldValue(
2413 Element element, HInstruction receiver, HInstruction value) { 2439 Element element, HInstruction receiver, HInstruction value) {
2440 assert(receiver == null || receiver == receiver.nonCheck());
2414 if (backend.isNative(element)) { 2441 if (backend.isNative(element)) {
2415 return; // TODO(14955): Remove this restriction? 2442 return; // TODO(14955): Remove this restriction?
2416 } 2443 }
2417 Map<HInstruction, HInstruction> map = 2444 Map<HInstruction, HInstruction> map =
2418 fieldValues.putIfAbsent(element, () => <HInstruction, HInstruction>{}); 2445 fieldValues.putIfAbsent(element, () => <HInstruction, HInstruction>{});
2419 map[receiver] = value; 2446 map[receiver] = value;
2420 } 2447 }
2421 2448
2422 /** 2449 /**
2423 * Returns the value stored in `receiver.element`. Returns null if 2450 * Returns the value stored in `receiver.element`. Returns `null` if we don't
2424 * we don't know. 2451 * know.
2425 */ 2452 */
2426 HInstruction lookupFieldValue(Element element, HInstruction receiver) { 2453 HInstruction lookupFieldValue(Element element, HInstruction receiver) {
2454 assert(receiver == null || receiver == receiver.nonCheck());
2427 Map<HInstruction, HInstruction> map = fieldValues[element]; 2455 Map<HInstruction, HInstruction> map = fieldValues[element];
2428 return (map == null) ? null : map[receiver]; 2456 return (map == null) ? null : map[receiver];
2429 } 2457 }
2430 2458
2431 /** 2459 /**
2432 * Kill all places that may be affected by this [instruction]. Also 2460 * Kill all places that may be affected by this [instruction]. Also update the
2433 * update the set of non-escaping objects in case [instruction] has 2461 * set of non-escaping objects in case [instruction] has non-escaping objects
2434 * non-escaping objects in its inputs. 2462 * in its inputs.
2435 */ 2463 */
2436 void killAffectedBy(HInstruction instruction) { 2464 void killAffectedBy(HInstruction instruction) {
2437 // Even if [instruction] does not have side effects, it may use 2465 // Even if [instruction] does not have side effects, it may use non-escaping
2438 // non-escaping objects and store them in a new object, which 2466 // objects and store them in a new object, which make these objects
2439 // make these objects escaping. 2467 // escaping.
2440 // TODO(ngeoffray): We need a new side effect flag to know whether
2441 // an instruction allocates an object.
2442 instruction.inputs.forEach((input) { 2468 instruction.inputs.forEach((input) {
2443 nonEscapingReceivers.remove(input); 2469 nonEscapingReceivers.remove(input.nonCheck());
2444 }); 2470 });
2445 2471
2446 if (instruction.sideEffects.changesInstanceProperty() || 2472 if (instruction.sideEffects.changesInstanceProperty() ||
2447 instruction.sideEffects.changesStaticProperty()) { 2473 instruction.sideEffects.changesStaticProperty()) {
2448 fieldValues.forEach((element, map) { 2474 fieldValues.forEach((element, map) {
2449 if (isFinal(element)) return; 2475 if (isFinal(element)) return;
2450 map.forEach((receiver, value) { 2476 map.forEach((receiver, value) {
2451 if (escapes(receiver)) { 2477 if (escapes(receiver)) {
2452 map[receiver] = null; 2478 map[receiver] = null;
2453 } 2479 }
(...skipping 30 matching lines...) Expand all
2484 keyedValues.putIfAbsent(receiver, () => <HInstruction, HInstruction>{}); 2510 keyedValues.putIfAbsent(receiver, () => <HInstruction, HInstruction>{});
2485 map[index] = value; 2511 map[index] = value;
2486 } 2512 }
2487 2513
2488 /** 2514 /**
2489 * Sets `receiver[index]` to contain [value]. Kills all potential 2515 * Sets `receiver[index]` to contain [value]. Kills all potential
2490 * places that may be affected by this update. 2516 * places that may be affected by this update.
2491 */ 2517 */
2492 void registerKeyedValueUpdate( 2518 void registerKeyedValueUpdate(
2493 HInstruction receiver, HInstruction index, HInstruction value) { 2519 HInstruction receiver, HInstruction index, HInstruction value) {
2494 nonEscapingReceivers.remove(value); 2520 nonEscapingReceivers.remove(value.nonCheck());
2495 keyedValues.forEach((key, values) { 2521 keyedValues.forEach((key, values) {
2496 if (mayAlias(receiver, key)) { 2522 if (mayAlias(receiver, key)) {
2497 // Typed arrays that are views of the same buffer may have different 2523 // Typed arrays that are views of the same buffer may have different
2498 // offsets or element sizes, unless they are the same typed array. 2524 // offsets or element sizes, unless they are the same typed array.
2499 bool weakIndex = couldBeTypedArray(key) && !mustAlias(receiver, key); 2525 bool weakIndex = couldBeTypedArray(key) && !mustAlias(receiver, key);
2500 values.forEach((otherIndex, otherValue) { 2526 values.forEach((otherIndex, otherValue) {
2501 if (weakIndex || mayAlias(index, otherIndex)) { 2527 if (weakIndex || mayAlias(index, otherIndex)) {
2502 values[otherIndex] = null; 2528 values[otherIndex] = null;
2503 } 2529 }
2504 }); 2530 });
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
2595 2621
2596 keyedValues.forEach((receiver, values) { 2622 keyedValues.forEach((receiver, values) {
2597 result.keyedValues[receiver] = 2623 result.keyedValues[receiver] =
2598 new Map<HInstruction, HInstruction>.from(values); 2624 new Map<HInstruction, HInstruction>.from(values);
2599 }); 2625 });
2600 2626
2601 result.nonEscapingReceivers.addAll(nonEscapingReceivers); 2627 result.nonEscapingReceivers.addAll(nonEscapingReceivers);
2602 return result; 2628 return result;
2603 } 2629 }
2604 } 2630 }
OLDNEW
« no previous file with comments | « no previous file | tests/compiler/dart2js_native/load_elim_refinement_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698