OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/crankshaft/hydrogen-instructions.h" | 5 #include "src/crankshaft/hydrogen-instructions.h" |
6 | 6 |
7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/base/safe_math.h" | 8 #include "src/base/safe_math.h" |
9 #include "src/crankshaft/hydrogen-infer-representation.h" | 9 #include "src/crankshaft/hydrogen-infer-representation.h" |
10 #include "src/double.h" | 10 #include "src/double.h" |
(...skipping 3108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3119 if (!input_rep.IsTagged()) { | 3119 if (!input_rep.IsTagged()) { |
3120 rep = rep.generalize(input_rep); | 3120 rep = rep.generalize(input_rep); |
3121 } | 3121 } |
3122 return rep; | 3122 return rep; |
3123 } | 3123 } |
3124 | 3124 |
3125 | 3125 |
3126 bool HAllocate::HandleSideEffectDominator(GVNFlag side_effect, | 3126 bool HAllocate::HandleSideEffectDominator(GVNFlag side_effect, |
3127 HValue* dominator) { | 3127 HValue* dominator) { |
3128 DCHECK(side_effect == kNewSpacePromotion); | 3128 DCHECK(side_effect == kNewSpacePromotion); |
| 3129 DCHECK(!IsAllocationFolded()); |
3129 Zone* zone = block()->zone(); | 3130 Zone* zone = block()->zone(); |
3130 Isolate* isolate = block()->isolate(); | 3131 Isolate* isolate = block()->isolate(); |
3131 if (!FLAG_use_allocation_folding) return false; | 3132 if (!FLAG_use_allocation_folding) return false; |
3132 | 3133 |
3133 // Try to fold allocations together with their dominating allocations. | 3134 // Try to fold allocations together with their dominating allocations. |
3134 if (!dominator->IsAllocate()) { | 3135 if (!dominator->IsAllocate()) { |
3135 if (FLAG_trace_allocation_folding) { | 3136 if (FLAG_trace_allocation_folding) { |
3136 PrintF("#%d (%s) cannot fold into #%d (%s)\n", | 3137 PrintF("#%d (%s) cannot fold into #%d (%s)\n", |
3137 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); | 3138 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); |
3138 } | 3139 } |
3139 return false; | 3140 return false; |
3140 } | 3141 } |
3141 | 3142 |
3142 // Check whether we are folding within the same block for local folding. | 3143 // Check whether we are folding within the same block for local folding. |
3143 if (FLAG_use_local_allocation_folding && dominator->block() != block()) { | 3144 if (FLAG_use_local_allocation_folding && dominator->block() != block()) { |
3144 if (FLAG_trace_allocation_folding) { | 3145 if (FLAG_trace_allocation_folding) { |
3145 PrintF("#%d (%s) cannot fold into #%d (%s), crosses basic blocks\n", | 3146 PrintF("#%d (%s) cannot fold into #%d (%s), crosses basic blocks\n", |
3146 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); | 3147 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); |
3147 } | 3148 } |
3148 return false; | 3149 return false; |
3149 } | 3150 } |
3150 | 3151 |
3151 HAllocate* dominator_allocate = HAllocate::cast(dominator); | 3152 HAllocate* dominator_allocate = HAllocate::cast(dominator); |
3152 HValue* dominator_size = dominator_allocate->size(); | 3153 HValue* dominator_size = dominator_allocate->size(); |
3153 HValue* current_size = size(); | 3154 HValue* current_size = size(); |
3154 | 3155 |
3155 // TODO(hpayer): Add support for non-constant allocation in dominator. | 3156 // TODO(hpayer): Add support for non-constant allocation in dominator. |
3156 if (!dominator_size->IsInteger32Constant()) { | 3157 if (!current_size->IsInteger32Constant() || |
| 3158 !dominator_size->IsInteger32Constant()) { |
3157 if (FLAG_trace_allocation_folding) { | 3159 if (FLAG_trace_allocation_folding) { |
3158 PrintF("#%d (%s) cannot fold into #%d (%s), " | 3160 PrintF("#%d (%s) cannot fold into #%d (%s), " |
3159 "dynamic allocation size in dominator\n", | 3161 "dynamic allocation size in dominator\n", |
3160 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); | 3162 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); |
3161 } | 3163 } |
3162 return false; | 3164 return false; |
3163 } | 3165 } |
3164 | 3166 |
3165 | 3167 |
3166 if (!IsFoldable(dominator_allocate)) { | 3168 if (!IsFoldable(dominator_allocate)) { |
3167 if (FLAG_trace_allocation_folding) { | 3169 if (FLAG_trace_allocation_folding) { |
3168 PrintF("#%d (%s) cannot fold into #%d (%s), different spaces\n", id(), | 3170 PrintF("#%d (%s) cannot fold into #%d (%s), different spaces\n", id(), |
3169 Mnemonic(), dominator->id(), dominator->Mnemonic()); | 3171 Mnemonic(), dominator->id(), dominator->Mnemonic()); |
3170 } | 3172 } |
3171 return false; | 3173 return false; |
3172 } | 3174 } |
3173 | 3175 |
3174 if (!has_size_upper_bound()) { | |
3175 if (FLAG_trace_allocation_folding) { | |
3176 PrintF("#%d (%s) cannot fold into #%d (%s), " | |
3177 "can't estimate total allocation size\n", | |
3178 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); | |
3179 } | |
3180 return false; | |
3181 } | |
3182 | |
3183 if (!current_size->IsInteger32Constant()) { | |
3184 // If it's not constant then it is a size_in_bytes calculation graph | |
3185 // like this: (const_header_size + const_element_size * size). | |
3186 DCHECK(current_size->IsInstruction()); | |
3187 | |
3188 HInstruction* current_instr = HInstruction::cast(current_size); | |
3189 if (!current_instr->Dominates(dominator_allocate)) { | |
3190 if (FLAG_trace_allocation_folding) { | |
3191 PrintF("#%d (%s) cannot fold into #%d (%s), dynamic size " | |
3192 "value does not dominate target allocation\n", | |
3193 id(), Mnemonic(), dominator_allocate->id(), | |
3194 dominator_allocate->Mnemonic()); | |
3195 } | |
3196 return false; | |
3197 } | |
3198 } | |
3199 | |
3200 DCHECK( | 3176 DCHECK( |
3201 (IsNewSpaceAllocation() && dominator_allocate->IsNewSpaceAllocation()) || | 3177 (IsNewSpaceAllocation() && dominator_allocate->IsNewSpaceAllocation()) || |
3202 (IsOldSpaceAllocation() && dominator_allocate->IsOldSpaceAllocation())); | 3178 (IsOldSpaceAllocation() && dominator_allocate->IsOldSpaceAllocation())); |
3203 | 3179 |
3204 // First update the size of the dominator allocate instruction. | 3180 // First update the size of the dominator allocate instruction. |
3205 dominator_size = dominator_allocate->size(); | 3181 dominator_size = dominator_allocate->size(); |
3206 int32_t original_object_size = | 3182 int32_t original_object_size = |
3207 HConstant::cast(dominator_size)->GetInteger32Constant(); | 3183 HConstant::cast(dominator_size)->GetInteger32Constant(); |
3208 int32_t dominator_size_constant = original_object_size; | 3184 int32_t dominator_size_constant = original_object_size; |
3209 | 3185 |
3210 if (MustAllocateDoubleAligned()) { | 3186 if (MustAllocateDoubleAligned()) { |
3211 if ((dominator_size_constant & kDoubleAlignmentMask) != 0) { | 3187 if ((dominator_size_constant & kDoubleAlignmentMask) != 0) { |
3212 dominator_size_constant += kDoubleSize / 2; | 3188 dominator_size_constant += kDoubleSize / 2; |
3213 } | 3189 } |
3214 } | 3190 } |
3215 | 3191 |
3216 int32_t current_size_max_value = size_upper_bound()->GetInteger32Constant(); | 3192 int32_t current_size_max_value = size()->GetInteger32Constant(); |
3217 int32_t new_dominator_size = dominator_size_constant + current_size_max_value; | 3193 int32_t new_dominator_size = dominator_size_constant + current_size_max_value; |
3218 | 3194 |
3219 // Since we clear the first word after folded memory, we cannot use the | 3195 // Since we clear the first word after folded memory, we cannot use the |
3220 // whole Page::kMaxRegularHeapObjectSize memory. | 3196 // whole Page::kMaxRegularHeapObjectSize memory. |
3221 if (new_dominator_size > Page::kMaxRegularHeapObjectSize - kPointerSize) { | 3197 if (new_dominator_size > Page::kMaxRegularHeapObjectSize - kPointerSize) { |
3222 if (FLAG_trace_allocation_folding) { | 3198 if (FLAG_trace_allocation_folding) { |
3223 PrintF("#%d (%s) cannot fold into #%d (%s) due to size: %d\n", | 3199 PrintF("#%d (%s) cannot fold into #%d (%s) due to size: %d\n", |
3224 id(), Mnemonic(), dominator_allocate->id(), | 3200 id(), Mnemonic(), dominator_allocate->id(), |
3225 dominator_allocate->Mnemonic(), new_dominator_size); | 3201 dominator_allocate->Mnemonic(), new_dominator_size); |
3226 } | 3202 } |
3227 return false; | 3203 return false; |
3228 } | 3204 } |
3229 | 3205 |
3230 HInstruction* new_dominator_size_value; | 3206 HInstruction* new_dominator_size_value = HConstant::CreateAndInsertBefore( |
3231 | 3207 isolate, zone, context(), new_dominator_size, Representation::None(), |
3232 if (current_size->IsInteger32Constant()) { | 3208 dominator_allocate); |
3233 new_dominator_size_value = HConstant::CreateAndInsertBefore( | |
3234 isolate, zone, context(), new_dominator_size, Representation::None(), | |
3235 dominator_allocate); | |
3236 } else { | |
3237 HValue* new_dominator_size_constant = HConstant::CreateAndInsertBefore( | |
3238 isolate, zone, context(), dominator_size_constant, | |
3239 Representation::Integer32(), dominator_allocate); | |
3240 | |
3241 // Add old and new size together and insert. | |
3242 current_size->ChangeRepresentation(Representation::Integer32()); | |
3243 | |
3244 new_dominator_size_value = HAdd::New( | |
3245 isolate, zone, context(), new_dominator_size_constant, current_size); | |
3246 new_dominator_size_value->ClearFlag(HValue::kCanOverflow); | |
3247 new_dominator_size_value->ChangeRepresentation(Representation::Integer32()); | |
3248 | |
3249 new_dominator_size_value->InsertBefore(dominator_allocate); | |
3250 } | |
3251 | 3209 |
3252 dominator_allocate->UpdateSize(new_dominator_size_value); | 3210 dominator_allocate->UpdateSize(new_dominator_size_value); |
3253 | 3211 |
3254 if (MustAllocateDoubleAligned()) { | 3212 if (MustAllocateDoubleAligned()) { |
3255 if (!dominator_allocate->MustAllocateDoubleAligned()) { | 3213 if (!dominator_allocate->MustAllocateDoubleAligned()) { |
3256 dominator_allocate->MakeDoubleAligned(); | 3214 dominator_allocate->MakeDoubleAligned(); |
3257 } | 3215 } |
3258 } | 3216 } |
3259 | 3217 |
3260 bool keep_heap_iterable = FLAG_log_gc || FLAG_heap_stats; | 3218 if (IsAllocationFoldingDominator()) { |
3261 #ifdef VERIFY_HEAP | 3219 DeleteAndReplaceWith(dominator_allocate); |
3262 keep_heap_iterable = keep_heap_iterable || FLAG_verify_heap; | 3220 if (FLAG_trace_allocation_folding) { |
3263 #endif | 3221 PrintF( |
3264 | 3222 "#%d (%s) folded dominator into #%d (%s), new dominator size: %d\n", |
3265 if (keep_heap_iterable) { | 3223 id(), Mnemonic(), dominator_allocate->id(), |
3266 dominator_allocate->MakePrefillWithFiller(); | 3224 dominator_allocate->Mnemonic(), new_dominator_size); |
3267 } else { | 3225 } |
3268 // TODO(hpayer): This is a short-term hack to make allocation mementos | 3226 return true; |
3269 // work again in new space. | |
3270 dominator_allocate->ClearNextMapWord(original_object_size); | |
3271 } | 3227 } |
3272 | 3228 |
3273 dominator_allocate->UpdateClearNextMapWord(MustClearNextMapWord()); | 3229 if (!dominator_allocate->IsAllocationFoldingDominator()) { |
| 3230 HAllocate* first_alloc = |
| 3231 HAllocate::New(isolate, zone, dominator_allocate->context(), |
| 3232 dominator_size, dominator_allocate->type(), |
| 3233 IsNewSpaceAllocation() ? NOT_TENURED : TENURED, |
| 3234 JS_OBJECT_TYPE, block()->graph()->GetConstant0()); |
| 3235 first_alloc->InsertAfter(dominator_allocate); |
| 3236 dominator_allocate->ReplaceAllUsesWith(first_alloc); |
| 3237 dominator_allocate->MakeAllocationFoldingDominator(); |
| 3238 first_alloc->MakeFoldedAllocation(dominator_allocate); |
| 3239 if (FLAG_trace_allocation_folding) { |
| 3240 PrintF("#%d (%s) inserted for dominator #%d (%s)\n", first_alloc->id(), |
| 3241 first_alloc->Mnemonic(), dominator_allocate->id(), |
| 3242 dominator_allocate->Mnemonic()); |
| 3243 } |
| 3244 } |
3274 | 3245 |
3275 // After that replace the dominated allocate instruction. | 3246 MakeFoldedAllocation(dominator_allocate); |
3276 HInstruction* inner_offset = HConstant::CreateAndInsertBefore( | |
3277 isolate, zone, context(), dominator_size_constant, Representation::None(), | |
3278 this); | |
3279 | 3247 |
3280 HInstruction* dominated_allocate_instr = HInnerAllocatedObject::New( | |
3281 isolate, zone, context(), dominator_allocate, inner_offset, type()); | |
3282 dominated_allocate_instr->InsertBefore(this); | |
3283 DeleteAndReplaceWith(dominated_allocate_instr); | |
3284 if (FLAG_trace_allocation_folding) { | 3248 if (FLAG_trace_allocation_folding) { |
3285 PrintF("#%d (%s) folded into #%d (%s)\n", | 3249 PrintF("#%d (%s) folded into #%d (%s), new dominator size: %d\n", id(), |
3286 id(), Mnemonic(), dominator_allocate->id(), | 3250 Mnemonic(), dominator_allocate->id(), dominator_allocate->Mnemonic(), |
3287 dominator_allocate->Mnemonic()); | 3251 new_dominator_size); |
3288 } | 3252 } |
3289 return true; | 3253 return true; |
3290 } | 3254 } |
3291 | 3255 |
3292 | 3256 |
3293 void HAllocate::UpdateFreeSpaceFiller(int32_t free_space_size) { | |
3294 DCHECK(filler_free_space_size_ != NULL); | |
3295 Zone* zone = block()->zone(); | |
3296 // We must explicitly force Smi representation here because on x64 we | |
3297 // would otherwise automatically choose int32, but the actual store | |
3298 // requires a Smi-tagged value. | |
3299 HConstant* new_free_space_size = HConstant::CreateAndInsertBefore( | |
3300 block()->isolate(), zone, context(), | |
3301 filler_free_space_size_->value()->GetInteger32Constant() + | |
3302 free_space_size, | |
3303 Representation::Smi(), filler_free_space_size_); | |
3304 filler_free_space_size_->UpdateValue(new_free_space_size); | |
3305 } | |
3306 | |
3307 | |
3308 void HAllocate::CreateFreeSpaceFiller(int32_t free_space_size) { | |
3309 DCHECK(filler_free_space_size_ == NULL); | |
3310 Isolate* isolate = block()->isolate(); | |
3311 Zone* zone = block()->zone(); | |
3312 HInstruction* free_space_instr = | |
3313 HInnerAllocatedObject::New(isolate, zone, context(), dominating_allocate_, | |
3314 dominating_allocate_->size(), type()); | |
3315 free_space_instr->InsertBefore(this); | |
3316 HConstant* filler_map = HConstant::CreateAndInsertAfter( | |
3317 zone, Unique<Map>::CreateImmovable(isolate->factory()->free_space_map()), | |
3318 true, free_space_instr); | |
3319 HInstruction* store_map = | |
3320 HStoreNamedField::New(isolate, zone, context(), free_space_instr, | |
3321 HObjectAccess::ForMap(), filler_map); | |
3322 store_map->SetFlag(HValue::kHasNoObservableSideEffects); | |
3323 store_map->InsertAfter(filler_map); | |
3324 | |
3325 // We must explicitly force Smi representation here because on x64 we | |
3326 // would otherwise automatically choose int32, but the actual store | |
3327 // requires a Smi-tagged value. | |
3328 HConstant* filler_size = | |
3329 HConstant::CreateAndInsertAfter(isolate, zone, context(), free_space_size, | |
3330 Representation::Smi(), store_map); | |
3331 // Must force Smi representation for x64 (see comment above). | |
3332 HObjectAccess access = HObjectAccess::ForMapAndOffset( | |
3333 isolate->factory()->free_space_map(), FreeSpace::kSizeOffset, | |
3334 Representation::Smi()); | |
3335 HStoreNamedField* store_size = HStoreNamedField::New( | |
3336 isolate, zone, context(), free_space_instr, access, filler_size); | |
3337 store_size->SetFlag(HValue::kHasNoObservableSideEffects); | |
3338 store_size->InsertAfter(filler_size); | |
3339 filler_free_space_size_ = store_size; | |
3340 } | |
3341 | |
3342 | |
3343 void HAllocate::ClearNextMapWord(int offset) { | |
3344 if (MustClearNextMapWord()) { | |
3345 Zone* zone = block()->zone(); | |
3346 HObjectAccess access = | |
3347 HObjectAccess::ForObservableJSObjectOffset(offset); | |
3348 HStoreNamedField* clear_next_map = | |
3349 HStoreNamedField::New(block()->isolate(), zone, context(), this, access, | |
3350 block()->graph()->GetConstant0()); | |
3351 clear_next_map->ClearAllSideEffects(); | |
3352 clear_next_map->InsertAfter(this); | |
3353 } | |
3354 } | |
3355 | |
3356 | |
3357 std::ostream& HAllocate::PrintDataTo(std::ostream& os) const { // NOLINT | 3257 std::ostream& HAllocate::PrintDataTo(std::ostream& os) const { // NOLINT |
3358 os << NameOf(size()) << " ("; | 3258 os << NameOf(size()) << " ("; |
3359 if (IsNewSpaceAllocation()) os << "N"; | 3259 if (IsNewSpaceAllocation()) os << "N"; |
3360 if (IsOldSpaceAllocation()) os << "P"; | 3260 if (IsOldSpaceAllocation()) os << "P"; |
3361 if (MustAllocateDoubleAligned()) os << "A"; | 3261 if (MustAllocateDoubleAligned()) os << "A"; |
3362 if (MustPrefillWithFiller()) os << "F"; | 3262 if (MustPrefillWithFiller()) os << "F"; |
3363 return os << ")"; | 3263 return os << ")"; |
3364 } | 3264 } |
3365 | 3265 |
3366 | 3266 |
(...skipping 766 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4133 case HObjectAccess::kExternalMemory: | 4033 case HObjectAccess::kExternalMemory: |
4134 os << "[external-memory]"; | 4034 os << "[external-memory]"; |
4135 break; | 4035 break; |
4136 } | 4036 } |
4137 | 4037 |
4138 return os << "@" << access.offset(); | 4038 return os << "@" << access.offset(); |
4139 } | 4039 } |
4140 | 4040 |
4141 } // namespace internal | 4041 } // namespace internal |
4142 } // namespace v8 | 4042 } // namespace v8 |
OLD | NEW |