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

Side by Side Diff: runtime/vm/flow_graph_optimizer.cc

Issue 868283002: Fix LoadOptimizer's handling of load/stores with constant indices for TypedData. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/bitfield.h ('k') | runtime/vm/locations.h » ('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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 #include "vm/flow_graph_optimizer.h" 5 #include "vm/flow_graph_optimizer.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/cha.h" 8 #include "vm/cha.h"
9 #include "vm/cpu.h" 9 #include "vm/cpu.h"
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 5069 matching lines...) Expand 10 before | Expand all | Expand 10 after
5080 // 5080 //
5081 // - for fields 5081 // - for fields
5082 // - *.f, *.@offs - field inside some object; 5082 // - *.f, *.@offs - field inside some object;
5083 // - X.f, X.@offs - field inside an allocated object X; 5083 // - X.f, X.@offs - field inside an allocated object X;
5084 // - for indexed accesses 5084 // - for indexed accesses
5085 // - *[*] - non-constant index inside some object; 5085 // - *[*] - non-constant index inside some object;
5086 // - *[C] - constant index inside some object; 5086 // - *[C] - constant index inside some object;
5087 // - X[*] - non-constant index inside an allocated object X; 5087 // - X[*] - non-constant index inside an allocated object X;
5088 // - X[C] - constant index inside an allocated object X. 5088 // - X[C] - constant index inside an allocated object X.
5089 // 5089 //
5090 // Constant indexed places are divided into two subcategories:
5091 //
5092 // - Access to homogeneous array-like objects: Array, ImmutableArray,
5093 // OneByteString, TwoByteString. These objects can only be accessed
5094 // on element by element basis with all elements having the same size.
5095 // This means X[C] aliases X[K] if and only if C === K.
5096 // - TypedData accesses. TypedData allow to read one of the primitive
5097 // data types at the given byte offset. When TypedData is accessed through
5098 // index operator on a typed array or a typed array view it is guaranteed
5099 // that the byte offset is always aligned by the element size. We write
5100 // these accesses as X[C|S], where C is constant byte offset and S is size
5101 // of the data type. Obviously X[C|S] and X[K|U] alias if and only if either
5102 // C = RoundDown(K, S) or K = RoundDown(C, U).
5103 // Note that not all accesses to typed data are aligned: e.g. ByteData
5104 // allows unanaligned access through it's get*/set* methods.
5105 // Check in Place::SetIndex ensures that we never create a place X[C|S]
5106 // such that C is not aligned by S.
5107 //
5090 // Separating allocations from other objects improves precision of the 5108 // Separating allocations from other objects improves precision of the
5091 // load forwarding pass because of the following two properties: 5109 // load forwarding pass because of the following two properties:
5092 // 5110 //
5093 // - if X can be proven to have no aliases itself (i.e. there is no other SSA 5111 // - if X can be proven to have no aliases itself (i.e. there is no other SSA
5094 // variable that points to X) then no place inside X can be aliased with any 5112 // variable that points to X) then no place inside X can be aliased with any
5095 // wildcard dependent place (*.f, *.@offs, *[*], *[C]); 5113 // wildcard dependent place (*.f, *.@offs, *[*], *[C]);
5096 // - given allocations X and Y no place inside X can be aliased with any place 5114 // - given allocations X and Y no place inside X can be aliased with any place
5097 // inside Y even if any of them or both escape. 5115 // inside Y even if any of them or both escape.
5098 // 5116 //
5099 // It important to realize that single place can belong to multiple aliases. 5117 // It important to realize that single place can belong to multiple aliases.
(...skipping 15 matching lines...) Expand all
5115 // being accessed and offset to the field. 5133 // being accessed and offset to the field.
5116 kVMField, 5134 kVMField,
5117 5135
5118 // Indexed location with a non-constant index. 5136 // Indexed location with a non-constant index.
5119 kIndexed, 5137 kIndexed,
5120 5138
5121 // Indexed location with a constant index. 5139 // Indexed location with a constant index.
5122 kConstantIndexed, 5140 kConstantIndexed,
5123 }; 5141 };
5124 5142
5143 // Size of the element accessed by constant index. Size is only important
5144 // for TypedData because those accesses can alias even when constant indexes
5145 // are not the same: X[0|4] aliases X[0|2] and X[2|2].
5146 enum ElementSize {
5147 // If indexed access is not a TypedData access then element size is not
5148 // important because there is only a single possible access size depending
5149 // on the receiver - X[C] aliases X[K] if and only if C == K.
5150 // This is the size set for Array, ImmutableArray, OneByteString and
5151 // TwoByteString accesses.
5152 kNoSize,
5153
5154 // 1 byte (Int8List, Uint8List, Uint8ClampedList).
5155 kInt8,
5156
5157 // 2 bytes (Int16List, Uint16List).
5158 kInt16,
5159
5160 // 4 bytes (Int32List, Uint32List, Float32List).
5161 kInt32,
5162
5163 // 8 bytes (Int64List, Uint64List, Float64List).
5164 kInt64,
5165
5166 // 16 bytes (Int32x4List, Float32x4List, Float64x2List).
5167 kInt128,
5168
5169 kLargestElementSize = kInt128,
5170 };
5171
5125 Place(const Place& other) 5172 Place(const Place& other)
5126 : ValueObject(), 5173 : ValueObject(),
5127 kind_(other.kind_), 5174 flags_(other.flags_),
5128 representation_(other.representation_),
5129 instance_(other.instance_), 5175 instance_(other.instance_),
5130 raw_selector_(other.raw_selector_), 5176 raw_selector_(other.raw_selector_),
5131 id_(other.id_) { 5177 id_(other.id_) {
5132 } 5178 }
5133 5179
5134 // Construct a place from instruction if instruction accesses any place. 5180 // Construct a place from instruction if instruction accesses any place.
5135 // Otherwise constructs kNone place. 5181 // Otherwise constructs kNone place.
5136 Place(Instruction* instr, bool* is_load, bool* is_store) 5182 Place(Instruction* instr, bool* is_load, bool* is_store)
5137 : kind_(kNone), 5183 : flags_(0),
5138 representation_(kNoRepresentation),
5139 instance_(NULL), 5184 instance_(NULL),
5140 raw_selector_(0), 5185 raw_selector_(0),
5141 id_(0) { 5186 id_(0) {
5142 switch (instr->tag()) { 5187 switch (instr->tag()) {
5143 case Instruction::kLoadField: { 5188 case Instruction::kLoadField: {
5144 LoadFieldInstr* load_field = instr->AsLoadField(); 5189 LoadFieldInstr* load_field = instr->AsLoadField();
5145 representation_ = load_field->representation(); 5190 set_representation(load_field->representation());
5146 instance_ = load_field->instance()->definition()->OriginalDefinition(); 5191 instance_ = load_field->instance()->definition()->OriginalDefinition();
5147 if (load_field->field() != NULL) { 5192 if (load_field->field() != NULL) {
5148 kind_ = kField; 5193 set_kind(kField);
5149 field_ = load_field->field(); 5194 field_ = load_field->field();
5150 } else { 5195 } else {
5151 kind_ = kVMField; 5196 set_kind(kVMField);
5152 offset_in_bytes_ = load_field->offset_in_bytes(); 5197 offset_in_bytes_ = load_field->offset_in_bytes();
5153 } 5198 }
5154 *is_load = true; 5199 *is_load = true;
5155 break; 5200 break;
5156 } 5201 }
5157 5202
5158 case Instruction::kStoreInstanceField: { 5203 case Instruction::kStoreInstanceField: {
5159 StoreInstanceFieldInstr* store = 5204 StoreInstanceFieldInstr* store =
5160 instr->AsStoreInstanceField(); 5205 instr->AsStoreInstanceField();
5161 representation_ = store->RequiredInputRepresentation( 5206 set_representation(store->RequiredInputRepresentation(
5162 StoreInstanceFieldInstr::kValuePos); 5207 StoreInstanceFieldInstr::kValuePos));
5163 instance_ = store->instance()->definition()->OriginalDefinition(); 5208 instance_ = store->instance()->definition()->OriginalDefinition();
5164 if (!store->field().IsNull()) { 5209 if (!store->field().IsNull()) {
5165 kind_ = kField; 5210 set_kind(kField);
5166 field_ = &store->field(); 5211 field_ = &store->field();
5167 } else { 5212 } else {
5168 kind_ = kVMField; 5213 set_kind(kVMField);
5169 offset_in_bytes_ = store->offset_in_bytes(); 5214 offset_in_bytes_ = store->offset_in_bytes();
5170 } 5215 }
5171 *is_store = true; 5216 *is_store = true;
5172 break; 5217 break;
5173 } 5218 }
5174 5219
5175 case Instruction::kLoadStaticField: 5220 case Instruction::kLoadStaticField:
5176 kind_ = kField; 5221 set_kind(kField);
5177 representation_ = instr->AsLoadStaticField()->representation(); 5222 set_representation(instr->AsLoadStaticField()->representation());
5178 field_ = &instr->AsLoadStaticField()->StaticField(); 5223 field_ = &instr->AsLoadStaticField()->StaticField();
5179 *is_load = true; 5224 *is_load = true;
5180 break; 5225 break;
5181 5226
5182 case Instruction::kStoreStaticField: 5227 case Instruction::kStoreStaticField:
5183 kind_ = kField; 5228 set_kind(kField);
5184 representation_ = instr->AsStoreStaticField()-> 5229 set_representation(instr->AsStoreStaticField()->
5185 RequiredInputRepresentation(StoreStaticFieldInstr::kValuePos); 5230 RequiredInputRepresentation(StoreStaticFieldInstr::kValuePos));
5186 field_ = &instr->AsStoreStaticField()->field(); 5231 field_ = &instr->AsStoreStaticField()->field();
5187 *is_store = true; 5232 *is_store = true;
5188 break; 5233 break;
5189 5234
5190 case Instruction::kLoadIndexed: { 5235 case Instruction::kLoadIndexed: {
5191 LoadIndexedInstr* load_indexed = instr->AsLoadIndexed(); 5236 LoadIndexedInstr* load_indexed = instr->AsLoadIndexed();
5192 representation_ = load_indexed->representation(); 5237 set_representation(load_indexed->representation());
5193 instance_ = load_indexed->array()->definition()->OriginalDefinition(); 5238 instance_ = load_indexed->array()->definition()->OriginalDefinition();
5194 SetIndex(load_indexed->index()->definition()); 5239 SetIndex(load_indexed->index()->definition(),
5240 load_indexed->index_scale(),
5241 load_indexed->class_id());
5195 *is_load = true; 5242 *is_load = true;
5196 break; 5243 break;
5197 } 5244 }
5198 5245
5199 case Instruction::kStoreIndexed: { 5246 case Instruction::kStoreIndexed: {
5200 StoreIndexedInstr* store_indexed = instr->AsStoreIndexed(); 5247 StoreIndexedInstr* store_indexed = instr->AsStoreIndexed();
5201 representation_ = store_indexed-> 5248 set_representation(store_indexed->
5202 RequiredInputRepresentation(StoreIndexedInstr::kValuePos); 5249 RequiredInputRepresentation(StoreIndexedInstr::kValuePos));
5203 instance_ = store_indexed->array()->definition()->OriginalDefinition(); 5250 instance_ = store_indexed->array()->definition()->OriginalDefinition();
5204 SetIndex(store_indexed->index()->definition()); 5251 SetIndex(store_indexed->index()->definition(),
5252 store_indexed->index_scale(),
5253 store_indexed->class_id());
5205 *is_store = true; 5254 *is_store = true;
5206 break; 5255 break;
5207 } 5256 }
5208 5257
5209 default: 5258 default:
5210 break; 5259 break;
5211 } 5260 }
5212 } 5261 }
5213 5262
5214 // Create object representing *[*] alias. 5263 // Create object representing *[*] alias.
5215 static Place* CreateAnyInstanceAnyIndexAlias(Isolate* isolate, 5264 static Place* CreateAnyInstanceAnyIndexAlias(Isolate* isolate,
5216 intptr_t id) { 5265 intptr_t id) {
5217 return Wrap(isolate, Place(kIndexed, NULL, 0), id); 5266 return Wrap(isolate, Place(
5267 EncodeFlags(kIndexed, kNoRepresentation, kNoSize),
5268 NULL,
5269 0), id);
5218 } 5270 }
5219 5271
5220 // Return least generic alias for this place. Given that aliases are 5272 // Return least generic alias for this place. Given that aliases are
5221 // essentially sets of places we define least generic alias as a smallest 5273 // essentially sets of places we define least generic alias as a smallest
5222 // alias that contains this place. 5274 // alias that contains this place.
5223 // 5275 //
5224 // We obtain such alias by a simple transformation: 5276 // We obtain such alias by a simple transformation:
5225 // 5277 //
5226 // - for places that depend on an instance X.f, X.@offs, X[i], X[C] 5278 // - for places that depend on an instance X.f, X.@offs, X[i], X[C]
5227 // we drop X if X is not an allocation because in this case X does not 5279 // we drop X if X is not an allocation because in this case X does not
5228 // posess an identity obtaining aliases *.f, *.@offs, *[i] and *[C] 5280 // posess an identity obtaining aliases *.f, *.@offs, *[i] and *[C]
5229 // respectively; 5281 // respectively;
5230 // - for non-constant indexed places X[i] we drop information about the 5282 // - for non-constant indexed places X[i] we drop information about the
5231 // index obtaining alias X[*]. 5283 // index obtaining alias X[*].
5284 // - we drop information about representation, but keep element size
5285 // if any.
5232 // 5286 //
5233 Place ToAlias() const { 5287 Place ToAlias() const {
5234 return Place( 5288 return Place(
5235 kind_, 5289 RepresentationBits::update(kNoRepresentation, flags_),
5236 (DependsOnInstance() && IsAllocation(instance())) ? instance() : NULL, 5290 (DependsOnInstance() && IsAllocation(instance())) ? instance() : NULL,
5237 (kind() == kIndexed) ? 0 : raw_selector_); 5291 (kind() == kIndexed) ? 0 : raw_selector_);
5238 } 5292 }
5239 5293
5240 bool DependsOnInstance() const { 5294 bool DependsOnInstance() const {
5241 switch (kind()) { 5295 switch (kind()) {
5242 case kField: 5296 case kField:
5243 case kVMField: 5297 case kVMField:
5244 case kIndexed: 5298 case kIndexed:
5245 case kConstantIndexed: 5299 case kConstantIndexed:
5246 return true; 5300 return true;
5247 5301
5248 case kNone: 5302 case kNone:
5249 return false; 5303 return false;
5250 } 5304 }
5251 5305
5252 UNREACHABLE(); 5306 UNREACHABLE();
5253 return false; 5307 return false;
5254 } 5308 }
5255 5309
5256 // Given instance dependent alias X.f, X.@offs, X[C], X[*] return 5310 // Given instance dependent alias X.f, X.@offs, X[C], X[*] return
5257 // wild-card dependent alias *.f, *.@offs, *[C] or *[*] respectively. 5311 // wild-card dependent alias *.f, *.@offs, *[C] or *[*] respectively.
5258 Place CopyWithoutInstance() const { 5312 Place CopyWithoutInstance() const {
5259 ASSERT(DependsOnInstance()); 5313 ASSERT(DependsOnInstance());
5260 return Place(kind_, NULL, raw_selector_); 5314 return Place(flags_, NULL, raw_selector_);
5261 } 5315 }
5262 5316
5263 // Given alias X[C] or *[C] return X[*] and *[*] respectively. 5317 // Given alias X[C] or *[C] return X[*] and *[*] respectively.
5264 Place CopyWithoutIndex() const { 5318 Place CopyWithoutIndex() const {
5265 ASSERT(kind_ == kConstantIndexed); 5319 ASSERT(kind() == kConstantIndexed);
5266 return Place(kIndexed, instance_, 0); 5320 return Place(EncodeFlags(kIndexed, kNoRepresentation, kNoSize),
5321 instance_,
5322 0);
5267 } 5323 }
5268 5324
5325 // Given alias X[ByteOffs|S] and a larger element size S', return
5326 // alias X[RoundDown(ByteOffs, S')|S'] - this is the byte offset of a larger
5327 // typed array element that contains this typed array element.
5328 // In other words this method computes the only possible place with the given
5329 // size that can alias this place (due to alignment restrictions).
5330 // For example for X[9|kInt8] and target size kInt32 we would return
5331 // X[8|kInt32].
5332 Place ToLargerElement(ElementSize to) const {
5333 ASSERT(kind() == kConstantIndexed);
5334 ASSERT(element_size() != kNoSize);
5335 ASSERT(element_size() < to);
5336 return Place(ElementSizeBits::update(to, flags_),
5337 instance_,
5338 RoundByteOffset(to, index_constant_));
5339 }
5340
5341
5269 intptr_t id() const { return id_; } 5342 intptr_t id() const { return id_; }
5270 5343
5271 Kind kind() const { return kind_; } 5344 Kind kind() const { return KindBits::decode(flags_); }
5272 5345
5273 Representation representation() const { return representation_; } 5346 Representation representation() const {
5347 return RepresentationBits::decode(flags_);
5348 }
5274 5349
5275 Definition* instance() const { 5350 Definition* instance() const {
5276 ASSERT(DependsOnInstance()); 5351 ASSERT(DependsOnInstance());
5277 return instance_; 5352 return instance_;
5278 } 5353 }
5279 5354
5280 void set_instance(Definition* def) { 5355 void set_instance(Definition* def) {
5281 ASSERT(DependsOnInstance()); 5356 ASSERT(DependsOnInstance());
5282 instance_ = def->OriginalDefinition(); 5357 instance_ = def->OriginalDefinition();
5283 } 5358 }
5284 5359
5285 const Field& field() const { 5360 const Field& field() const {
5286 ASSERT(kind_ == kField); 5361 ASSERT(kind() == kField);
5287 return *field_; 5362 return *field_;
5288 } 5363 }
5289 5364
5290 intptr_t offset_in_bytes() const { 5365 intptr_t offset_in_bytes() const {
5291 ASSERT(kind_ == kVMField); 5366 ASSERT(kind() == kVMField);
5292 return offset_in_bytes_; 5367 return offset_in_bytes_;
5293 } 5368 }
5294 5369
5295 Definition* index() const { 5370 Definition* index() const {
5296 ASSERT(kind_ == kIndexed); 5371 ASSERT(kind() == kIndexed);
5297 return index_; 5372 return index_;
5298 } 5373 }
5299 5374
5375 ElementSize element_size() const {
5376 return ElementSizeBits::decode(flags_);
5377 }
5378
5300 intptr_t index_constant() const { 5379 intptr_t index_constant() const {
5301 ASSERT(kind_ == kConstantIndexed); 5380 ASSERT(kind() == kConstantIndexed);
5302 return index_constant_; 5381 return index_constant_;
5303 } 5382 }
5304 5383
5305 static const char* DefinitionName(Definition* def) { 5384 static const char* DefinitionName(Definition* def) {
5306 if (def == NULL) { 5385 if (def == NULL) {
5307 return "*"; 5386 return "*";
5308 } else { 5387 } else {
5309 return Isolate::Current()->current_zone()->PrintToString( 5388 return Isolate::Current()->current_zone()->PrintToString(
5310 "v%" Pd, def->ssa_temp_index()); 5389 "v%" Pd, def->ssa_temp_index());
5311 } 5390 }
5312 } 5391 }
5313 5392
5314 const char* ToCString() const { 5393 const char* ToCString() const {
5315 switch (kind_) { 5394 switch (kind()) {
5316 case kNone: 5395 case kNone:
5317 return "<none>"; 5396 return "<none>";
5318 5397
5319 case kField: { 5398 case kField: {
5320 const char* field_name = String::Handle(field().name()).ToCString(); 5399 const char* field_name = String::Handle(field().name()).ToCString();
5321 if (field().is_static()) { 5400 if (field().is_static()) {
5322 return Isolate::Current()->current_zone()->PrintToString( 5401 return Isolate::Current()->current_zone()->PrintToString(
5323 "<%s>", field_name); 5402 "<%s>", field_name);
5324 } else { 5403 } else {
5325 return Isolate::Current()->current_zone()->PrintToString( 5404 return Isolate::Current()->current_zone()->PrintToString(
5326 "<%s.%s>", DefinitionName(instance()), field_name); 5405 "<%s.%s>", DefinitionName(instance()), field_name);
5327 } 5406 }
5328 } 5407 }
5329 5408
5330 case kVMField: 5409 case kVMField:
5331 return Isolate::Current()->current_zone()->PrintToString( 5410 return Isolate::Current()->current_zone()->PrintToString(
5332 "<%s.@%" Pd ">", 5411 "<%s.@%" Pd ">",
5333 DefinitionName(instance()), 5412 DefinitionName(instance()),
5334 offset_in_bytes()); 5413 offset_in_bytes());
5335 5414
5336 case kIndexed: 5415 case kIndexed:
5337 return Isolate::Current()->current_zone()->PrintToString( 5416 return Isolate::Current()->current_zone()->PrintToString(
5338 "<%s[%s]>", 5417 "<%s[%s]>",
5339 DefinitionName(instance()), 5418 DefinitionName(instance()),
5340 DefinitionName(index())); 5419 DefinitionName(index()));
5341 5420
5342 case kConstantIndexed: 5421 case kConstantIndexed:
5343 return Isolate::Current()->current_zone()->PrintToString( 5422 if (element_size() == kNoSize) {
5344 "<%s[%" Pd "]>", 5423 return Isolate::Current()->current_zone()->PrintToString(
5345 DefinitionName(instance()), 5424 "<%s[%" Pd "]>",
5346 index_constant()); 5425 DefinitionName(instance()),
5426 index_constant());
5427 } else {
5428 return Isolate::Current()->current_zone()->PrintToString(
5429 "<%s[%" Pd "|%" Pd "]>",
5430 DefinitionName(instance()),
5431 index_constant(),
5432 ElementSizeMultiplier(element_size()));
5433 }
5347 } 5434 }
5348 UNREACHABLE(); 5435 UNREACHABLE();
5349 return "<?>"; 5436 return "<?>";
5350 } 5437 }
5351 5438
5352 bool IsFinalField() const { 5439 bool IsFinalField() const {
5353 return (kind() == kField) && field().is_final(); 5440 return (kind() == kField) && field().is_final();
5354 } 5441 }
5355 5442
5356 intptr_t Hashcode() const { 5443 intptr_t Hashcode() const {
5357 return (kind_ * 63 + reinterpret_cast<intptr_t>(instance_)) * 31 + 5444 return (flags_ * 63 + reinterpret_cast<intptr_t>(instance_)) * 31 +
5358 representation_ * 15 + FieldHashcode(); 5445 FieldHashcode();
5359 } 5446 }
5360 5447
5361 bool Equals(const Place* other) const { 5448 bool Equals(const Place* other) const {
5362 return (kind_ == other->kind_) && 5449 return (flags_ == other->flags_) &&
5363 (representation_ == other->representation_) &&
5364 (instance_ == other->instance_) && 5450 (instance_ == other->instance_) &&
5365 SameField(other); 5451 SameField(other);
5366 } 5452 }
5367 5453
5368 // Create a zone allocated copy of this place and assign given id to it. 5454 // Create a zone allocated copy of this place and assign given id to it.
5369 static Place* Wrap(Isolate* isolate, const Place& place, intptr_t id); 5455 static Place* Wrap(Isolate* isolate, const Place& place, intptr_t id);
5370 5456
5371 static bool IsAllocation(Definition* defn) { 5457 static bool IsAllocation(Definition* defn) {
5372 return (defn != NULL) && 5458 return (defn != NULL) &&
5373 (defn->IsAllocateObject() || 5459 (defn->IsAllocateObject() ||
5374 defn->IsCreateArray() || 5460 defn->IsCreateArray() ||
5375 defn->IsAllocateUninitializedContext() || 5461 defn->IsAllocateUninitializedContext() ||
5376 (defn->IsStaticCall() && 5462 (defn->IsStaticCall() &&
5377 defn->AsStaticCall()->IsRecognizedFactory())); 5463 defn->AsStaticCall()->IsRecognizedFactory()));
5378 } 5464 }
5379 5465
5380 private: 5466 private:
5381 Place(Kind kind, Definition* instance, intptr_t selector) 5467 Place(uword flags, Definition* instance, intptr_t selector)
5382 : kind_(kind), 5468 : flags_(flags),
5383 representation_(kNoRepresentation),
5384 instance_(instance), 5469 instance_(instance),
5385 raw_selector_(selector), 5470 raw_selector_(selector),
5386 id_(0) { 5471 id_(0) {
5387 } 5472 }
5388 5473
5389 bool SameField(const Place* other) const { 5474 bool SameField(const Place* other) const {
5390 return (kind_ == kField) ? (field().raw() == other->field().raw()) 5475 return (kind() == kField) ? (field().raw() == other->field().raw())
5391 : (offset_in_bytes_ == other->offset_in_bytes_); 5476 : (offset_in_bytes_ == other->offset_in_bytes_);
5392 } 5477 }
5393 5478
5394 intptr_t FieldHashcode() const { 5479 intptr_t FieldHashcode() const {
5395 return (kind_ == kField) ? reinterpret_cast<intptr_t>(field().raw()) 5480 return (kind() == kField) ? reinterpret_cast<intptr_t>(field().raw())
5396 : offset_in_bytes_; 5481 : offset_in_bytes_;
5397 } 5482 }
5398 5483
5399 void SetIndex(Definition* index) { 5484 void set_representation(Representation rep) {
5485 flags_ = RepresentationBits::update(rep, flags_);
5486 }
5487
5488 void set_kind(Kind kind) {
5489 flags_ = KindBits::update(kind, flags_);
5490 }
5491
5492 void set_element_size(ElementSize scale) {
5493 flags_ = ElementSizeBits::update(scale, flags_);
5494 }
5495
5496 void SetIndex(Definition* index, intptr_t scale, intptr_t class_id) {
5400 ConstantInstr* index_constant = index->AsConstant(); 5497 ConstantInstr* index_constant = index->AsConstant();
5401 if ((index_constant != NULL) && index_constant->value().IsSmi()) { 5498 if ((index_constant != NULL) && index_constant->value().IsSmi()) {
5402 kind_ = kConstantIndexed; 5499 const intptr_t index_value = Smi::Cast(index_constant->value()).Value();
5403 index_constant_ = Smi::Cast(index_constant->value()).Value(); 5500 const ElementSize size = ElementSizeFor(class_id);
5404 } else { 5501 const bool is_typed_data = (size != kNoSize);
5405 kind_ = kIndexed; 5502
5406 index_ = index; 5503 // If we are writing into the typed data scale the index to
5504 // get byte offset. Otherwise ignore the scale.
5505 if (!is_typed_data) {
5506 scale = 1;
5507 }
5508
5509 // Guard against potential multiplication overflow and negative indices.
5510 if ((0 <= index_value) && (index_value < (kMaxInt32 / scale))) {
5511 const intptr_t scaled_index = index_value * scale;
5512
5513 // Guard against unaligned byte offsets.
5514 if (!is_typed_data ||
5515 Utils::IsAligned(scaled_index, ElementSizeMultiplier(size))) {
5516 set_kind(kConstantIndexed);
5517 set_element_size(size);
5518 index_constant_ = scaled_index;
5519 return;
5520 }
5521 }
5522
5523 // Fallthrough: create generic _[*] place.
5524 }
5525
5526 set_kind(kIndexed);
5527 index_ = index;
5528 }
5529
5530 static uword EncodeFlags(Kind kind, Representation rep, ElementSize scale) {
5531 ASSERT((kind == kConstantIndexed) || (scale == kNoSize));
5532 return KindBits::encode(kind) |
5533 RepresentationBits::encode(rep) |
5534 ElementSizeBits::encode(scale);
5535 }
5536
5537 static ElementSize ElementSizeFor(intptr_t class_id) {
5538 switch (class_id) {
5539 case kArrayCid:
5540 case kImmutableArrayCid:
5541 case kOneByteStringCid:
5542 case kTwoByteStringCid:
5543 // Object arrays and strings do not allow accessing them through
5544 // different types. No need to attach scale.
5545 return kNoSize;
5546
5547 case kTypedDataInt8ArrayCid:
5548 case kTypedDataUint8ArrayCid:
5549 case kTypedDataUint8ClampedArrayCid:
5550 case kExternalTypedDataUint8ArrayCid:
5551 case kExternalTypedDataUint8ClampedArrayCid:
5552 return kInt8;
5553
5554 case kTypedDataInt16ArrayCid:
5555 case kTypedDataUint16ArrayCid:
5556 return kInt16;
5557
5558 case kTypedDataInt32ArrayCid:
5559 case kTypedDataUint32ArrayCid:
5560 case kTypedDataFloat32ArrayCid:
5561 return kInt32;
5562
5563 case kTypedDataInt64ArrayCid:
5564 case kTypedDataUint64ArrayCid:
5565 case kTypedDataFloat64ArrayCid:
5566 return kInt64;
5567
5568 case kTypedDataInt32x4ArrayCid:
5569 case kTypedDataFloat32x4ArrayCid:
5570 case kTypedDataFloat64x2ArrayCid:
5571 return kInt128;
5572
5573 default:
5574 UNREACHABLE();
5575 return kNoSize;
5407 } 5576 }
5408 } 5577 }
5409 5578
5410 Kind kind_; 5579 static intptr_t ElementSizeMultiplier(ElementSize size) {
5411 Representation representation_; 5580 return 1 << (static_cast<intptr_t>(size) - static_cast<intptr_t>(kInt8));
5581 }
5582
5583 static intptr_t RoundByteOffset(ElementSize size, intptr_t offset) {
5584 return offset & ~(ElementSizeMultiplier(size) - 1);
5585 }
5586
5587 typedef BitField<Kind, 0, 3> KindBits;
5588 typedef BitField<Representation, KindBits::kNextBit, 11> RepresentationBits;
5589 typedef BitField<
5590 ElementSize, RepresentationBits::kNextBit, 3> ElementSizeBits;
5591
5592 uword flags_;
5412 Definition* instance_; 5593 Definition* instance_;
5413 union { 5594 union {
5414 intptr_t raw_selector_; 5595 intptr_t raw_selector_;
5415 const Field* field_; 5596 const Field* field_;
5416 intptr_t offset_in_bytes_; 5597 intptr_t offset_in_bytes_;
5417 intptr_t index_constant_; 5598 intptr_t index_constant_;
5418 Definition* index_; 5599 Definition* index_;
5419 }; 5600 };
5420 5601
5421 intptr_t id_; 5602 intptr_t id_;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
5493 AliasedSet(Isolate* isolate, 5674 AliasedSet(Isolate* isolate,
5494 DirectChainedHashMap<PointerKeyValueTrait<Place> >* places_map, 5675 DirectChainedHashMap<PointerKeyValueTrait<Place> >* places_map,
5495 ZoneGrowableArray<Place*>* places, 5676 ZoneGrowableArray<Place*>* places,
5496 PhiPlaceMoves* phi_moves) 5677 PhiPlaceMoves* phi_moves)
5497 : isolate_(isolate), 5678 : isolate_(isolate),
5498 places_map_(places_map), 5679 places_map_(places_map),
5499 places_(*places), 5680 places_(*places),
5500 phi_moves_(phi_moves), 5681 phi_moves_(phi_moves),
5501 aliases_(5), 5682 aliases_(5),
5502 aliases_map_(), 5683 aliases_map_(),
5684 typed_data_access_sizes_(),
5503 representatives_(), 5685 representatives_(),
5504 killed_(), 5686 killed_(),
5505 aliased_by_effects_(new(isolate) BitVector(isolate, places->length())) { 5687 aliased_by_effects_(new(isolate) BitVector(isolate, places->length())) {
5506 InsertAlias(Place::CreateAnyInstanceAnyIndexAlias(isolate_, 5688 InsertAlias(Place::CreateAnyInstanceAnyIndexAlias(isolate_,
5507 kAnyInstanceAnyIndexAlias)); 5689 kAnyInstanceAnyIndexAlias));
5508 for (intptr_t i = 0; i < places_.length(); i++) { 5690 for (intptr_t i = 0; i < places_.length(); i++) {
5509 AddRepresentative(places_[i]); 5691 AddRepresentative(places_[i]);
5510 } 5692 }
5511 ComputeKillSets(); 5693 ComputeKillSets();
5512 } 5694 }
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
5601 if (alias->kind() == Place::kConstantIndexed) { 5783 if (alias->kind() == Place::kConstantIndexed) {
5602 if (CanBeAliased(alias->instance())) { 5784 if (CanBeAliased(alias->instance())) {
5603 EnsureSet(&representatives_, kAnyConstantIndexedAlias)-> 5785 EnsureSet(&representatives_, kAnyConstantIndexedAlias)->
5604 Add(place->id()); 5786 Add(place->id());
5605 } 5787 }
5606 5788
5607 if (alias->instance() == NULL) { 5789 if (alias->instance() == NULL) {
5608 EnsureSet(&representatives_, kUnknownInstanceConstantIndexedAlias)-> 5790 EnsureSet(&representatives_, kUnknownInstanceConstantIndexedAlias)->
5609 Add(place->id()); 5791 Add(place->id());
5610 } 5792 }
5793
5794 // Collect all element sizes used to access TypedData arrays in
5795 // the function. This is used to skip sizes without representatives
5796 // when computing kill sets.
5797 if (alias->element_size() != Place::kNoSize) {
5798 typed_data_access_sizes_.Add(alias->element_size());
5799 }
5611 } else if ((alias->kind() == Place::kIndexed) && 5800 } else if ((alias->kind() == Place::kIndexed) &&
5612 CanBeAliased(place->instance())) { 5801 CanBeAliased(place->instance())) {
5613 EnsureSet(&representatives_, kAnyAllocationIndexedAlias)-> 5802 EnsureSet(&representatives_, kAnyAllocationIndexedAlias)->
5614 Add(place->id()); 5803 Add(place->id());
5615 } 5804 }
5616 5805
5617 if (!IsIndependentFromEffects(place)) { 5806 if (!IsIndependentFromEffects(place)) {
5618 aliased_by_effects_->Add(place->id()); 5807 aliased_by_effects_->Add(place->id());
5619 } 5808 }
5620 } 5809 }
(...skipping 28 matching lines...) Expand all
5649 } 5838 }
5650 5839
5651 const Place* CanonicalizeAlias(const Place& alias) { 5840 const Place* CanonicalizeAlias(const Place& alias) {
5652 const Place* canonical = aliases_map_.Lookup(&alias); 5841 const Place* canonical = aliases_map_.Lookup(&alias);
5653 if (canonical == NULL) { 5842 if (canonical == NULL) {
5654 canonical = Place::Wrap(isolate_, 5843 canonical = Place::Wrap(isolate_,
5655 alias, 5844 alias,
5656 kAnyInstanceAnyIndexAlias + aliases_.length()); 5845 kAnyInstanceAnyIndexAlias + aliases_.length());
5657 InsertAlias(canonical); 5846 InsertAlias(canonical);
5658 } 5847 }
5848 ASSERT(aliases_map_.Lookup(&alias) == canonical);
5659 return canonical; 5849 return canonical;
5660 } 5850 }
5661 5851
5662 BitVector* GetRepresentativesSet(intptr_t alias) { 5852 BitVector* GetRepresentativesSet(intptr_t alias) {
5663 return (alias < representatives_.length()) ? representatives_[alias] : NULL; 5853 return (alias < representatives_.length()) ? representatives_[alias] : NULL;
5664 } 5854 }
5665 5855
5666 BitVector* EnsureSet(GrowableArray<BitVector*>* sets, 5856 BitVector* EnsureSet(GrowableArray<BitVector*>* sets,
5667 intptr_t alias) { 5857 intptr_t alias) {
5668 while (sets->length() <= alias) { 5858 while (sets->length() <= alias) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
5718 AddAllRepresentatives(alias, kAnyAllocationIndexedAlias); 5908 AddAllRepresentatives(alias, kAnyAllocationIndexedAlias);
5719 } else if (CanBeAliased(alias->instance())) { 5909 } else if (CanBeAliased(alias->instance())) {
5720 // X[*] aliases with X[C]. 5910 // X[*] aliases with X[C].
5721 // If X can be aliased then X[*] also aliases with *[C], *[*]. 5911 // If X can be aliased then X[*] also aliases with *[C], *[*].
5722 CrossAlias(alias, kAnyInstanceAnyIndexAlias); 5912 CrossAlias(alias, kAnyInstanceAnyIndexAlias);
5723 AddAllRepresentatives(alias, kUnknownInstanceConstantIndexedAlias); 5913 AddAllRepresentatives(alias, kUnknownInstanceConstantIndexedAlias);
5724 } 5914 }
5725 break; 5915 break;
5726 5916
5727 case Place::kConstantIndexed: // Either X[C] or *[C] alias. 5917 case Place::kConstantIndexed: // Either X[C] or *[C] alias.
5918 if (alias->element_size() != Place::kNoSize) {
5919 const bool has_aliased_instance =
5920 (alias->instance() != NULL) && CanBeAliased(alias->instance());
5921
5922 // If this is a TypedData access then X[C|S] aliases larger elements
5923 // covering this one X[RoundDown(C, S')|S'] for all S' > S and
5924 // all smaller elements being covered by this one X[C'|S'] for
5925 // some S' < S and all C' such that C = RoundDown(C', S).
5926 // In the loop below it's enough to only propagate aliasing to
5927 // larger aliases because propagation is symmetric: smaller aliases
5928 // (if there are any) would update kill set for this alias when they
5929 // are visited.
5930 for (intptr_t i = static_cast<intptr_t>(alias->element_size()) + 1;
5931 i <= Place::kLargestElementSize;
5932 i++) {
5933 // Skip element sizes that a guaranteed to have no representatives.
5934 if (!typed_data_access_sizes_.Contains(alias->element_size())) {
5935 continue;
5936 }
5937
5938 // X[C|S] aliases with X[RoundDown(C, S')|S'] and likewise
5939 // *[C|S] aliases with *[RoundDown(C, S')|S'].
5940 const Place larger_alias =
5941 alias->ToLargerElement(static_cast<Place::ElementSize>(i));
5942 CrossAlias(alias, larger_alias);
5943 if (has_aliased_instance) {
5944 // If X is an aliased instance then X[C|S] aliases
5945 // with *[RoundDown(C, S')|S'].
5946 CrossAlias(alias, larger_alias.CopyWithoutInstance());
5947 }
5948 }
5949 }
5950
5728 if (alias->instance() == NULL) { 5951 if (alias->instance() == NULL) {
5729 // *[C] aliases with X[C], X[*], *[*]. 5952 // *[C] aliases with X[C], X[*], *[*].
5730 AddAllRepresentatives(alias, kAnyAllocationIndexedAlias); 5953 AddAllRepresentatives(alias, kAnyAllocationIndexedAlias);
5731 CrossAlias(alias, kAnyInstanceAnyIndexAlias); 5954 CrossAlias(alias, kAnyInstanceAnyIndexAlias);
5732 } else { 5955 } else {
5733 // X[C] aliases with X[*]. 5956 // X[C] aliases with X[*].
5734 // If X can be aliased then X[C] also aliases with *[C], *[*]. 5957 // If X can be aliased then X[C] also aliases with *[C], *[*].
5735 CrossAlias(alias, alias->CopyWithoutIndex()); 5958 CrossAlias(alias, alias->CopyWithoutIndex());
5736 if (CanBeAliased(alias->instance())) { 5959 if (CanBeAliased(alias->instance())) {
5737 CrossAlias(alias, alias->CopyWithoutInstance()); 5960 CrossAlias(alias, alias->CopyWithoutInstance());
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
5910 6133
5911 const ZoneGrowableArray<Place*>& places_; 6134 const ZoneGrowableArray<Place*>& places_;
5912 6135
5913 const PhiPlaceMoves* phi_moves_; 6136 const PhiPlaceMoves* phi_moves_;
5914 6137
5915 // A list of all seen aliases and a map that allows looking up canonical 6138 // A list of all seen aliases and a map that allows looking up canonical
5916 // alias object. 6139 // alias object.
5917 GrowableArray<const Place*> aliases_; 6140 GrowableArray<const Place*> aliases_;
5918 DirectChainedHashMap<PointerKeyValueTrait<const Place> > aliases_map_; 6141 DirectChainedHashMap<PointerKeyValueTrait<const Place> > aliases_map_;
5919 6142
6143 SmallSet<Place::ElementSize> typed_data_access_sizes_;
6144
5920 // Maps alias id to set of ids of places representing the alias. 6145 // Maps alias id to set of ids of places representing the alias.
5921 // Place represents an alias if this alias is least generic alias for 6146 // Place represents an alias if this alias is least generic alias for
5922 // the place. 6147 // the place.
5923 // (see ToAlias for the definition of least generic alias). 6148 // (see ToAlias for the definition of least generic alias).
5924 GrowableArray<BitVector*> representatives_; 6149 GrowableArray<BitVector*> representatives_;
5925 6150
5926 // Maps alias id to set of ids of places aliased. 6151 // Maps alias id to set of ids of places aliased.
5927 GrowableArray<BitVector*> killed_; 6152 GrowableArray<BitVector*> killed_;
5928 6153
5929 // Set of ids of places that can be affected by side-effects other than 6154 // Set of ids of places that can be affected by side-effects other than
(...skipping 2451 matching lines...) Expand 10 before | Expand all | Expand 10 after
8381 8606
8382 // Insert materializations at environment uses. 8607 // Insert materializations at environment uses.
8383 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { 8608 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) {
8384 CreateMaterializationAt( 8609 CreateMaterializationAt(
8385 exits_collector_.exits()[i], alloc, *slots); 8610 exits_collector_.exits()[i], alloc, *slots);
8386 } 8611 }
8387 } 8612 }
8388 8613
8389 8614
8390 } // namespace dart 8615 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/bitfield.h ('k') | runtime/vm/locations.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698