| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |