OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 2348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2359 is_internalized_string_(is_internalize_string), | 2359 is_internalized_string_(is_internalize_string), |
2360 is_not_in_new_space_(is_not_in_new_space), | 2360 is_not_in_new_space_(is_not_in_new_space), |
2361 is_cell_(is_cell), | 2361 is_cell_(is_cell), |
2362 boolean_value_(boolean_value) { | 2362 boolean_value_(boolean_value) { |
2363 ASSERT(!handle.is_null()); | 2363 ASSERT(!handle.is_null()); |
2364 ASSERT(!type.IsTaggedNumber()); | 2364 ASSERT(!type.IsTaggedNumber()); |
2365 Initialize(r); | 2365 Initialize(r); |
2366 } | 2366 } |
2367 | 2367 |
2368 | 2368 |
| 2369 HConstant::HConstant(Handle<Map> handle, |
| 2370 UniqueValueId unique_id) |
| 2371 : HTemplateInstruction<0>(HType::Tagged()), |
| 2372 handle_(handle), |
| 2373 unique_id_(unique_id), |
| 2374 has_smi_value_(false), |
| 2375 has_int32_value_(false), |
| 2376 has_double_value_(false), |
| 2377 has_external_reference_value_(false), |
| 2378 is_internalized_string_(false), |
| 2379 is_not_in_new_space_(true), |
| 2380 is_cell_(false), |
| 2381 boolean_value_(false) { |
| 2382 ASSERT(!handle.is_null()); |
| 2383 Initialize(Representation::Tagged()); |
| 2384 } |
| 2385 |
| 2386 |
2369 HConstant::HConstant(int32_t integer_value, | 2387 HConstant::HConstant(int32_t integer_value, |
2370 Representation r, | 2388 Representation r, |
2371 bool is_not_in_new_space, | 2389 bool is_not_in_new_space, |
2372 Handle<Object> optional_handle) | 2390 Handle<Object> optional_handle) |
2373 : handle_(optional_handle), | 2391 : handle_(optional_handle), |
2374 unique_id_(), | 2392 unique_id_(), |
2375 has_smi_value_(Smi::IsValid(integer_value)), | 2393 has_smi_value_(Smi::IsValid(integer_value)), |
2376 has_int32_value_(true), | 2394 has_int32_value_(true), |
2377 has_double_value_(true), | 2395 has_double_value_(true), |
2378 has_external_reference_value_(false), | 2396 has_external_reference_value_(false), |
(...skipping 794 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3173 if (!input_rep.IsTagged()) { | 3191 if (!input_rep.IsTagged()) { |
3174 rep = rep.generalize(input_rep); | 3192 rep = rep.generalize(input_rep); |
3175 } | 3193 } |
3176 return rep; | 3194 return rep; |
3177 } | 3195 } |
3178 | 3196 |
3179 | 3197 |
3180 void HAllocate::HandleSideEffectDominator(GVNFlag side_effect, | 3198 void HAllocate::HandleSideEffectDominator(GVNFlag side_effect, |
3181 HValue* dominator) { | 3199 HValue* dominator) { |
3182 ASSERT(side_effect == kChangesNewSpacePromotion); | 3200 ASSERT(side_effect == kChangesNewSpacePromotion); |
| 3201 Zone* zone = block()->zone(); |
3183 if (!FLAG_use_allocation_folding) return; | 3202 if (!FLAG_use_allocation_folding) return; |
3184 | 3203 |
3185 // Try to fold allocations together with their dominating allocations. | 3204 // Try to fold allocations together with their dominating allocations. |
3186 if (!dominator->IsAllocate()) { | 3205 if (!dominator->IsAllocate()) { |
3187 if (FLAG_trace_allocation_folding) { | 3206 if (FLAG_trace_allocation_folding) { |
3188 PrintF("#%d (%s) cannot fold into #%d (%s)\n", | 3207 PrintF("#%d (%s) cannot fold into #%d (%s)\n", |
3189 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); | 3208 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); |
3190 } | 3209 } |
3191 return; | 3210 return; |
3192 } | 3211 } |
3193 | 3212 |
3194 HAllocate* dominator_allocate_instr = HAllocate::cast(dominator); | 3213 HAllocate* dominator_allocate = HAllocate::cast(dominator); |
3195 HValue* dominator_size = dominator_allocate_instr->size(); | 3214 HValue* dominator_size = dominator_allocate->size(); |
3196 HValue* current_size = size(); | 3215 HValue* current_size = size(); |
3197 // We can just fold allocations that are guaranteed in new space. | 3216 |
3198 // TODO(hpayer): Add support for non-constant allocation in dominator. | 3217 // TODO(hpayer): Add support for non-constant allocation in dominator. |
3199 if (!IsNewSpaceAllocation() || !current_size->IsInteger32Constant() || | 3218 if (!current_size->IsInteger32Constant() || |
3200 !dominator_allocate_instr->IsNewSpaceAllocation() || | |
3201 !dominator_size->IsInteger32Constant()) { | 3219 !dominator_size->IsInteger32Constant()) { |
3202 if (FLAG_trace_allocation_folding) { | 3220 if (FLAG_trace_allocation_folding) { |
3203 PrintF("#%d (%s) cannot fold into #%d (%s)\n", | 3221 PrintF("#%d (%s) cannot fold into #%d (%s), dynamic allocation size\n", |
3204 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); | 3222 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); |
3205 } | 3223 } |
3206 return; | 3224 return; |
3207 } | 3225 } |
3208 | 3226 |
| 3227 dominator_allocate = GetFoldableDominator(dominator_allocate); |
| 3228 if (dominator_allocate == NULL) { |
| 3229 return; |
| 3230 } |
| 3231 |
| 3232 ASSERT((IsNewSpaceAllocation() && |
| 3233 dominator_allocate->IsNewSpaceAllocation()) || |
| 3234 (IsOldDataSpaceAllocation() && |
| 3235 dominator_allocate->IsOldDataSpaceAllocation()) || |
| 3236 (IsOldPointerSpaceAllocation() && |
| 3237 dominator_allocate->IsOldPointerSpaceAllocation())); |
| 3238 |
3209 // First update the size of the dominator allocate instruction. | 3239 // First update the size of the dominator allocate instruction. |
| 3240 dominator_size = dominator_allocate->size(); |
3210 int32_t dominator_size_constant = | 3241 int32_t dominator_size_constant = |
3211 HConstant::cast(dominator_size)->GetInteger32Constant(); | 3242 HConstant::cast(dominator_size)->GetInteger32Constant(); |
3212 int32_t current_size_constant = | 3243 int32_t current_size_constant = |
3213 HConstant::cast(current_size)->GetInteger32Constant(); | 3244 HConstant::cast(current_size)->GetInteger32Constant(); |
3214 int32_t new_dominator_size = dominator_size_constant + current_size_constant; | 3245 int32_t new_dominator_size = dominator_size_constant + current_size_constant; |
3215 | 3246 |
3216 if (MustAllocateDoubleAligned()) { | 3247 if (MustAllocateDoubleAligned()) { |
3217 if (!dominator_allocate_instr->MustAllocateDoubleAligned()) { | 3248 if (!dominator_allocate->MustAllocateDoubleAligned()) { |
3218 dominator_allocate_instr->MakeDoubleAligned(); | 3249 dominator_allocate->MakeDoubleAligned(); |
3219 } | 3250 } |
3220 if ((dominator_size_constant & kDoubleAlignmentMask) != 0) { | 3251 if ((dominator_size_constant & kDoubleAlignmentMask) != 0) { |
3221 dominator_size_constant += kDoubleSize / 2; | 3252 dominator_size_constant += kDoubleSize / 2; |
3222 new_dominator_size += kDoubleSize / 2; | 3253 new_dominator_size += kDoubleSize / 2; |
3223 } | 3254 } |
3224 } | 3255 } |
3225 | 3256 |
3226 if (new_dominator_size > Page::kMaxNonCodeHeapObjectSize) { | 3257 if (new_dominator_size > Page::kMaxNonCodeHeapObjectSize) { |
3227 if (FLAG_trace_allocation_folding) { | 3258 if (FLAG_trace_allocation_folding) { |
3228 PrintF("#%d (%s) cannot fold into #%d (%s) due to size: %d\n", | 3259 PrintF("#%d (%s) cannot fold into #%d (%s) due to size: %d\n", |
3229 id(), Mnemonic(), dominator->id(), dominator->Mnemonic(), | 3260 id(), Mnemonic(), dominator_allocate->id(), |
3230 new_dominator_size); | 3261 dominator_allocate->Mnemonic(), new_dominator_size); |
3231 } | 3262 } |
3232 return; | 3263 return; |
3233 } | 3264 } |
3234 HBasicBlock* block = dominator->block(); | 3265 |
3235 Zone* zone = block->zone(); | 3266 HInstruction* new_dominator_size_constant = HConstant::CreateAndInsertBefore( |
3236 HInstruction* new_dominator_size_constant = | 3267 zone, context(), new_dominator_size, dominator_allocate); |
3237 HConstant::New(zone, context(), new_dominator_size); | 3268 dominator_allocate->UpdateSize(new_dominator_size_constant); |
3238 new_dominator_size_constant->InsertBefore(dominator_allocate_instr); | |
3239 dominator_allocate_instr->UpdateSize(new_dominator_size_constant); | |
3240 | 3269 |
3241 #ifdef VERIFY_HEAP | 3270 #ifdef VERIFY_HEAP |
3242 if (FLAG_verify_heap) { | 3271 if (FLAG_verify_heap && dominator_allocate->IsNewSpaceAllocation()) { |
3243 dominator_allocate_instr->MakePrefillWithFiller(); | 3272 dominator_allocate->MakePrefillWithFiller(); |
3244 } | 3273 } |
3245 #endif | 3274 #endif |
3246 | 3275 |
3247 // After that replace the dominated allocate instruction. | 3276 // After that replace the dominated allocate instruction. |
3248 HInstruction* dominated_allocate_instr = | 3277 HInstruction* dominated_allocate_instr = |
3249 HInnerAllocatedObject::New(zone, | 3278 HInnerAllocatedObject::New(zone, |
3250 context(), | 3279 context(), |
3251 dominator_allocate_instr, | 3280 dominator_allocate, |
3252 dominator_size_constant, | 3281 dominator_size_constant, |
3253 type()); | 3282 type()); |
3254 dominated_allocate_instr->InsertBefore(this); | 3283 dominated_allocate_instr->InsertBefore(this); |
3255 DeleteAndReplaceWith(dominated_allocate_instr); | 3284 DeleteAndReplaceWith(dominated_allocate_instr); |
3256 if (FLAG_trace_allocation_folding) { | 3285 if (FLAG_trace_allocation_folding) { |
3257 PrintF("#%d (%s) folded into #%d (%s)\n", | 3286 PrintF("#%d (%s) folded into #%d (%s)\n", |
3258 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); | 3287 id(), Mnemonic(), dominator_allocate->id(), |
| 3288 dominator_allocate->Mnemonic()); |
3259 } | 3289 } |
3260 } | 3290 } |
3261 | 3291 |
3262 | 3292 |
| 3293 HAllocate* HAllocate::GetFoldableDominator(HAllocate* dominator) { |
| 3294 if (!IsFoldable(dominator)) { |
| 3295 // We cannot hoist old space allocations over new space allocations. |
| 3296 if (IsNewSpaceAllocation() || dominator->IsNewSpaceAllocation()) { |
| 3297 if (FLAG_trace_allocation_folding) { |
| 3298 PrintF("#%d (%s) cannot fold into #%d (%s), new space hoisting\n", |
| 3299 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); |
| 3300 } |
| 3301 return NULL; |
| 3302 } |
| 3303 |
| 3304 HAllocate* dominator_dominator = dominator->dominating_allocate_; |
| 3305 |
| 3306 // We can hoist old data space allocations over an old pointer space |
| 3307 // allocation and vice versa. For that we have to check the dominator |
| 3308 // of the dominator allocate instruction. |
| 3309 if (dominator_dominator == NULL) { |
| 3310 dominating_allocate_ = dominator; |
| 3311 if (FLAG_trace_allocation_folding) { |
| 3312 PrintF("#%d (%s) cannot fold into #%d (%s), different spaces\n", |
| 3313 id(), Mnemonic(), dominator->id(), dominator->Mnemonic()); |
| 3314 } |
| 3315 return NULL; |
| 3316 } |
| 3317 |
| 3318 // We can just fold old space allocations that are in the same basic block, |
| 3319 // since it is not guaranteed that we fill up the whole allocated old |
| 3320 // space memory. |
| 3321 // TODO(hpayer): Remove this limitation and add filler maps for each each |
| 3322 // allocation as soon as we have store elimination. |
| 3323 if (block()->block_id() != dominator_dominator->block()->block_id()) { |
| 3324 if (FLAG_trace_allocation_folding) { |
| 3325 PrintF("#%d (%s) cannot fold into #%d (%s), different basic blocks\n", |
| 3326 id(), Mnemonic(), dominator_dominator->id(), |
| 3327 dominator_dominator->Mnemonic()); |
| 3328 } |
| 3329 return NULL; |
| 3330 } |
| 3331 |
| 3332 ASSERT((IsOldDataSpaceAllocation() && |
| 3333 dominator_dominator->IsOldDataSpaceAllocation()) || |
| 3334 (IsOldPointerSpaceAllocation() && |
| 3335 dominator_dominator->IsOldPointerSpaceAllocation())); |
| 3336 |
| 3337 int32_t current_size = HConstant::cast(size())->GetInteger32Constant(); |
| 3338 HStoreNamedField* dominator_free_space_size = |
| 3339 dominator->filler_free_space_size_; |
| 3340 if (dominator_free_space_size != NULL) { |
| 3341 // We already hoisted one old space allocation, i.e., we already installed |
| 3342 // a filler map. Hence, we just have to update the free space size. |
| 3343 dominator->UpdateFreeSpaceFiller(current_size); |
| 3344 } else { |
| 3345 // This is the first old space allocation that gets hoisted. We have to |
| 3346 // install a filler map since the follwing allocation may cause a GC. |
| 3347 dominator->CreateFreeSpaceFiller(current_size); |
| 3348 } |
| 3349 |
| 3350 // We can hoist the old space allocation over the actual dominator. |
| 3351 return dominator_dominator; |
| 3352 } |
| 3353 return dominator; |
| 3354 } |
| 3355 |
| 3356 |
| 3357 void HAllocate::UpdateFreeSpaceFiller(int32_t free_space_size) { |
| 3358 ASSERT(filler_free_space_size_ != NULL); |
| 3359 Zone* zone = block()->zone(); |
| 3360 HConstant* new_free_space_size = HConstant::CreateAndInsertBefore( |
| 3361 zone, |
| 3362 context(), |
| 3363 filler_free_space_size_->value()->GetInteger32Constant() + |
| 3364 free_space_size, |
| 3365 filler_free_space_size_); |
| 3366 filler_free_space_size_->UpdateValue(new_free_space_size); |
| 3367 } |
| 3368 |
| 3369 |
| 3370 void HAllocate::CreateFreeSpaceFiller(int32_t free_space_size) { |
| 3371 ASSERT(filler_free_space_size_ == NULL); |
| 3372 Zone* zone = block()->zone(); |
| 3373 int32_t dominator_size = |
| 3374 HConstant::cast(dominating_allocate_->size())->GetInteger32Constant(); |
| 3375 HInstruction* free_space_instr = |
| 3376 HInnerAllocatedObject::New(zone, context(), dominating_allocate_, |
| 3377 dominator_size, type()); |
| 3378 free_space_instr->InsertBefore(this); |
| 3379 HConstant* filler_map = HConstant::New( |
| 3380 zone, |
| 3381 context(), |
| 3382 isolate()->factory()->free_space_map(), |
| 3383 UniqueValueId(isolate()->heap()->free_space_map())); |
| 3384 filler_map->InsertAfter(free_space_instr); |
| 3385 HInstruction* store_map = HStoreNamedField::New(zone, context(), |
| 3386 free_space_instr, HObjectAccess::ForMap(), filler_map); |
| 3387 store_map->SetFlag(HValue::kHasNoObservableSideEffects); |
| 3388 store_map->InsertAfter(filler_map); |
| 3389 |
| 3390 HConstant* filler_size = HConstant::CreateAndInsertAfter( |
| 3391 zone, context(), free_space_size, store_map); |
| 3392 HObjectAccess access = |
| 3393 HObjectAccess::ForJSObjectOffset(FreeSpace::kSizeOffset); |
| 3394 HStoreNamedField* store_size = HStoreNamedField::New(zone, context(), |
| 3395 free_space_instr, access, filler_size); |
| 3396 store_size->SetFlag(HValue::kHasNoObservableSideEffects); |
| 3397 store_size->InsertAfter(filler_size); |
| 3398 filler_free_space_size_ = store_size; |
| 3399 } |
| 3400 |
| 3401 |
3263 void HAllocate::PrintDataTo(StringStream* stream) { | 3402 void HAllocate::PrintDataTo(StringStream* stream) { |
3264 size()->PrintNameTo(stream); | 3403 size()->PrintNameTo(stream); |
3265 stream->Add(" ("); | 3404 stream->Add(" ("); |
3266 if (IsNewSpaceAllocation()) stream->Add("N"); | 3405 if (IsNewSpaceAllocation()) stream->Add("N"); |
3267 if (IsOldPointerSpaceAllocation()) stream->Add("P"); | 3406 if (IsOldPointerSpaceAllocation()) stream->Add("P"); |
3268 if (IsOldDataSpaceAllocation()) stream->Add("D"); | 3407 if (IsOldDataSpaceAllocation()) stream->Add("D"); |
3269 if (MustAllocateDoubleAligned()) stream->Add("A"); | 3408 if (MustAllocateDoubleAligned()) stream->Add("A"); |
3270 if (MustPrefillWithFiller()) stream->Add("F"); | 3409 if (MustPrefillWithFiller()) stream->Add("F"); |
3271 stream->Add(")"); | 3410 stream->Add(")"); |
3272 } | 3411 } |
(...skipping 721 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3994 break; | 4133 break; |
3995 case kExternalMemory: | 4134 case kExternalMemory: |
3996 stream->Add("[external-memory]"); | 4135 stream->Add("[external-memory]"); |
3997 break; | 4136 break; |
3998 } | 4137 } |
3999 | 4138 |
4000 stream->Add("@%d", offset()); | 4139 stream->Add("@%d", offset()); |
4001 } | 4140 } |
4002 | 4141 |
4003 } } // namespace v8::internal | 4142 } } // namespace v8::internal |
OLD | NEW |