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

Side by Side Diff: src/crankshaft/hydrogen-instructions.cc

Issue 1899813003: [crankshaft] Fragmentation-free allocation folding. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 7 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
« no previous file with comments | « src/crankshaft/hydrogen-instructions.h ('k') | src/crankshaft/ia32/lithium-codegen-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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
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
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
OLDNEW
« no previous file with comments | « src/crankshaft/hydrogen-instructions.h ('k') | src/crankshaft/ia32/lithium-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698