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

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

Powered by Google App Engine
This is Rietveld 408576698