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 3248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3259 // Doing this each dictionary entry always directly points to the check that | 3259 // Doing this each dictionary entry always directly points to the check that |
3260 // is dominating the code being examined now. | 3260 // is dominating the code being examined now. |
3261 // We also track the current "offset" of the index expression and use it to | 3261 // We also track the current "offset" of the index expression and use it to |
3262 // decide if any check is already "covered" (so it can be removed) or not. | 3262 // decide if any check is already "covered" (so it can be removed) or not. |
3263 class BoundsCheckBbData: public ZoneObject { | 3263 class BoundsCheckBbData: public ZoneObject { |
3264 public: | 3264 public: |
3265 BoundsCheckKey* Key() const { return key_; } | 3265 BoundsCheckKey* Key() const { return key_; } |
3266 int32_t LowerOffset() const { return lower_offset_; } | 3266 int32_t LowerOffset() const { return lower_offset_; } |
3267 int32_t UpperOffset() const { return upper_offset_; } | 3267 int32_t UpperOffset() const { return upper_offset_; } |
3268 HBasicBlock* BasicBlock() const { return basic_block_; } | 3268 HBasicBlock* BasicBlock() const { return basic_block_; } |
3269 HBoundsCheck* Check() const { return check_; } | 3269 HBoundsCheck* LowerCheck() const { return lower_check_; } |
| 3270 HBoundsCheck* UpperCheck() const { return upper_check_; } |
3270 BoundsCheckBbData* NextInBasicBlock() const { return next_in_bb_; } | 3271 BoundsCheckBbData* NextInBasicBlock() const { return next_in_bb_; } |
3271 BoundsCheckBbData* FatherInDominatorTree() const { return father_in_dt_; } | 3272 BoundsCheckBbData* FatherInDominatorTree() const { return father_in_dt_; } |
3272 | 3273 |
3273 bool OffsetIsCovered(int32_t offset) const { | 3274 bool OffsetIsCovered(int32_t offset) const { |
3274 return offset >= LowerOffset() && offset <= UpperOffset(); | 3275 return offset >= LowerOffset() && offset <= UpperOffset(); |
3275 } | 3276 } |
3276 | 3277 |
3277 // This method removes new_check and modifies the current check so that it | 3278 bool HasSingleCheck() { return lower_check_ == upper_check_; } |
3278 // also "covers" what new_check covered. | 3279 |
3279 // The obvious precondition is that new_check follows Check() in the | 3280 // The goal of this method is to modify either upper_offset_ or |
3280 // same basic block, and that new_offset is not covered (otherwise we | 3281 // lower_offset_ so that also new_offset is covered (the covered |
3281 // could simply remove new_check). | |
3282 // As a consequence LowerOffset() or UpperOffset() change (the covered | |
3283 // range grows). | 3282 // range grows). |
3284 // | 3283 // |
3285 // In the general case the check covering the current range should be like | 3284 // The precondition is that new_check follows UpperCheck() and |
3286 // these two checks: | 3285 // LowerCheck() in the same basic block, and that new_offset is not |
3287 // 0 <= Key()->IndexBase() + LowerOffset() | 3286 // covered (otherwise we could simply remove new_check). |
3288 // Key()->IndexBase() + UpperOffset() < Key()->Length() | |
3289 // | 3287 // |
3290 // We can transform the second check like this: | 3288 // If HasSingleCheck() is true then new_check is added as "second check" |
3291 // Key()->IndexBase() + LowerOffset() < | 3289 // (either upper or lower; note that HasSingleCheck() becomes false). |
3292 // Key()->Length() + (LowerOffset() - UpperOffset()) | 3290 // Otherwise one of the current checks is modified so that it also covers |
3293 // so we can handle both checks with a single unsigned comparison. | 3291 // new_offset, and new_check is removed. |
3294 // | |
3295 // The bulk of this method changes Check()->index() and Check()->length() | |
3296 // replacing them with new HAdd instructions to perform the transformation | |
3297 // described above. | |
3298 void CoverCheck(HBoundsCheck* new_check, | 3292 void CoverCheck(HBoundsCheck* new_check, |
3299 int32_t new_offset) { | 3293 int32_t new_offset) { |
3300 ASSERT(new_check->index()->representation().IsInteger32()); | 3294 ASSERT(new_check->index()->representation().IsInteger32()); |
| 3295 bool keep_new_check = false; |
3301 | 3296 |
3302 if (new_offset > upper_offset_) { | 3297 if (new_offset > upper_offset_) { |
3303 upper_offset_ = new_offset; | 3298 upper_offset_ = new_offset; |
| 3299 if (HasSingleCheck()) { |
| 3300 keep_new_check = true; |
| 3301 upper_check_ = new_check; |
| 3302 } else { |
| 3303 BuildOffsetAdd(upper_check_, |
| 3304 &added_upper_index_, |
| 3305 &added_upper_offset_, |
| 3306 Key()->IndexBase(), |
| 3307 new_check->index()->representation(), |
| 3308 new_offset); |
| 3309 upper_check_->SetOperandAt(0, added_upper_index_); |
| 3310 } |
3304 } else if (new_offset < lower_offset_) { | 3311 } else if (new_offset < lower_offset_) { |
3305 lower_offset_ = new_offset; | 3312 lower_offset_ = new_offset; |
| 3313 if (HasSingleCheck()) { |
| 3314 keep_new_check = true; |
| 3315 lower_check_ = new_check; |
| 3316 } else { |
| 3317 BuildOffsetAdd(lower_check_, |
| 3318 &added_lower_index_, |
| 3319 &added_lower_offset_, |
| 3320 Key()->IndexBase(), |
| 3321 new_check->index()->representation(), |
| 3322 new_offset); |
| 3323 lower_check_->SetOperandAt(0, added_lower_index_); |
| 3324 } |
3306 } else { | 3325 } else { |
3307 ASSERT(false); | 3326 ASSERT(false); |
3308 } | 3327 } |
3309 | 3328 |
3310 BuildOffsetAdd(&added_index_, | 3329 if (!keep_new_check) { |
3311 &added_index_offset_, | 3330 new_check->DeleteAndReplaceWith(NULL); |
3312 Key()->IndexBase(), | 3331 } |
3313 new_check->index()->representation(), | |
3314 lower_offset_); | |
3315 Check()->SetOperandAt(0, added_index_); | |
3316 BuildOffsetAdd(&added_length_, | |
3317 &added_length_offset_, | |
3318 Key()->Length(), | |
3319 new_check->length()->representation(), | |
3320 lower_offset_ - upper_offset_); | |
3321 Check()->SetOperandAt(1, added_length_); | |
3322 | |
3323 new_check->DeleteAndReplaceWith(NULL); | |
3324 } | 3332 } |
3325 | 3333 |
3326 void RemoveZeroOperations() { | 3334 void RemoveZeroOperations() { |
3327 RemoveZeroAdd(&added_index_, &added_index_offset_); | 3335 RemoveZeroAdd(&added_lower_index_, &added_lower_offset_); |
3328 RemoveZeroAdd(&added_length_, &added_length_offset_); | 3336 RemoveZeroAdd(&added_upper_index_, &added_upper_offset_); |
3329 } | 3337 } |
3330 | 3338 |
3331 BoundsCheckBbData(BoundsCheckKey* key, | 3339 BoundsCheckBbData(BoundsCheckKey* key, |
3332 int32_t lower_offset, | 3340 int32_t lower_offset, |
3333 int32_t upper_offset, | 3341 int32_t upper_offset, |
3334 HBasicBlock* bb, | 3342 HBasicBlock* bb, |
3335 HBoundsCheck* check, | 3343 HBoundsCheck* lower_check, |
| 3344 HBoundsCheck* upper_check, |
3336 BoundsCheckBbData* next_in_bb, | 3345 BoundsCheckBbData* next_in_bb, |
3337 BoundsCheckBbData* father_in_dt) | 3346 BoundsCheckBbData* father_in_dt) |
3338 : key_(key), | 3347 : key_(key), |
3339 lower_offset_(lower_offset), | 3348 lower_offset_(lower_offset), |
3340 upper_offset_(upper_offset), | 3349 upper_offset_(upper_offset), |
3341 basic_block_(bb), | 3350 basic_block_(bb), |
3342 check_(check), | 3351 lower_check_(lower_check), |
3343 added_index_offset_(NULL), | 3352 upper_check_(upper_check), |
3344 added_index_(NULL), | 3353 added_lower_index_(NULL), |
3345 added_length_offset_(NULL), | 3354 added_lower_offset_(NULL), |
3346 added_length_(NULL), | 3355 added_upper_index_(NULL), |
| 3356 added_upper_offset_(NULL), |
3347 next_in_bb_(next_in_bb), | 3357 next_in_bb_(next_in_bb), |
3348 father_in_dt_(father_in_dt) { } | 3358 father_in_dt_(father_in_dt) { } |
3349 | 3359 |
3350 private: | 3360 private: |
3351 BoundsCheckKey* key_; | 3361 BoundsCheckKey* key_; |
3352 int32_t lower_offset_; | 3362 int32_t lower_offset_; |
3353 int32_t upper_offset_; | 3363 int32_t upper_offset_; |
3354 HBasicBlock* basic_block_; | 3364 HBasicBlock* basic_block_; |
3355 HBoundsCheck* check_; | 3365 HBoundsCheck* lower_check_; |
3356 HConstant* added_index_offset_; | 3366 HBoundsCheck* upper_check_; |
3357 HAdd* added_index_; | 3367 HAdd* added_lower_index_; |
3358 HConstant* added_length_offset_; | 3368 HConstant* added_lower_offset_; |
3359 HAdd* added_length_; | 3369 HAdd* added_upper_index_; |
| 3370 HConstant* added_upper_offset_; |
3360 BoundsCheckBbData* next_in_bb_; | 3371 BoundsCheckBbData* next_in_bb_; |
3361 BoundsCheckBbData* father_in_dt_; | 3372 BoundsCheckBbData* father_in_dt_; |
3362 | 3373 |
3363 void BuildOffsetAdd(HAdd** add, | 3374 void BuildOffsetAdd(HBoundsCheck* check, |
| 3375 HAdd** add, |
3364 HConstant** constant, | 3376 HConstant** constant, |
3365 HValue* original_value, | 3377 HValue* original_value, |
3366 Representation representation, | 3378 Representation representation, |
3367 int32_t new_offset) { | 3379 int32_t new_offset) { |
3368 HConstant* new_constant = new(BasicBlock()->zone()) | 3380 HConstant* new_constant = new(BasicBlock()->zone()) |
3369 HConstant(Handle<Object>(Smi::FromInt(new_offset)), | 3381 HConstant(Handle<Object>(Smi::FromInt(new_offset)), |
3370 Representation::Integer32()); | 3382 Representation::Integer32()); |
3371 if (*add == NULL) { | 3383 if (*add == NULL) { |
3372 new_constant->InsertBefore(Check()); | 3384 new_constant->InsertBefore(check); |
3373 *add = new(BasicBlock()->zone()) HAdd(NULL, | 3385 *add = new(BasicBlock()->zone()) HAdd(NULL, |
3374 original_value, | 3386 original_value, |
3375 new_constant); | 3387 new_constant); |
3376 (*add)->AssumeRepresentation(representation); | 3388 (*add)->AssumeRepresentation(representation); |
3377 (*add)->InsertBefore(Check()); | 3389 (*add)->InsertBefore(check); |
3378 } else { | 3390 } else { |
3379 new_constant->InsertBefore(*add); | 3391 new_constant->InsertBefore(*add); |
3380 (*constant)->DeleteAndReplaceWith(new_constant); | 3392 (*constant)->DeleteAndReplaceWith(new_constant); |
3381 } | 3393 } |
3382 *constant = new_constant; | 3394 *constant = new_constant; |
3383 } | 3395 } |
3384 | 3396 |
3385 void RemoveZeroAdd(HAdd** add, HConstant** constant) { | 3397 void RemoveZeroAdd(HAdd** add, HConstant** constant) { |
3386 if (*add != NULL && (*constant)->Integer32Value() == 0) { | 3398 if (*add != NULL && (*constant)->Integer32Value() == 0) { |
3387 (*add)->DeleteAndReplaceWith((*add)->left()); | 3399 (*add)->DeleteAndReplaceWith((*add)->left()); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3440 BoundsCheckKey* key = | 3452 BoundsCheckKey* key = |
3441 BoundsCheckKey::Create(zone(), check, &offset); | 3453 BoundsCheckKey::Create(zone(), check, &offset); |
3442 BoundsCheckBbData** data_p = table->LookupOrInsert(key, zone()); | 3454 BoundsCheckBbData** data_p = table->LookupOrInsert(key, zone()); |
3443 BoundsCheckBbData* data = *data_p; | 3455 BoundsCheckBbData* data = *data_p; |
3444 if (data == NULL) { | 3456 if (data == NULL) { |
3445 bb_data_list = new(zone()) BoundsCheckBbData(key, | 3457 bb_data_list = new(zone()) BoundsCheckBbData(key, |
3446 offset, | 3458 offset, |
3447 offset, | 3459 offset, |
3448 bb, | 3460 bb, |
3449 check, | 3461 check, |
| 3462 check, |
3450 bb_data_list, | 3463 bb_data_list, |
3451 NULL); | 3464 NULL); |
3452 *data_p = bb_data_list; | 3465 *data_p = bb_data_list; |
3453 } else if (data->OffsetIsCovered(offset)) { | 3466 } else if (data->OffsetIsCovered(offset)) { |
3454 check->DeleteAndReplaceWith(NULL); | 3467 check->DeleteAndReplaceWith(NULL); |
3455 } else if (data->BasicBlock() == bb) { | 3468 } else if (data->BasicBlock() == bb) { |
3456 data->CoverCheck(check, offset); | 3469 data->CoverCheck(check, offset); |
3457 } else { | 3470 } else { |
3458 int32_t new_lower_offset = offset < data->LowerOffset() | 3471 int32_t new_lower_offset = offset < data->LowerOffset() |
3459 ? offset | 3472 ? offset |
3460 : data->LowerOffset(); | 3473 : data->LowerOffset(); |
3461 int32_t new_upper_offset = offset > data->UpperOffset() | 3474 int32_t new_upper_offset = offset > data->UpperOffset() |
3462 ? offset | 3475 ? offset |
3463 : data->UpperOffset(); | 3476 : data->UpperOffset(); |
3464 bb_data_list = new(zone()) BoundsCheckBbData(key, | 3477 bb_data_list = new(zone()) BoundsCheckBbData(key, |
3465 new_lower_offset, | 3478 new_lower_offset, |
3466 new_upper_offset, | 3479 new_upper_offset, |
3467 bb, | 3480 bb, |
3468 check, | 3481 data->LowerCheck(), |
| 3482 data->UpperCheck(), |
3469 bb_data_list, | 3483 bb_data_list, |
3470 data); | 3484 data); |
3471 table->Insert(key, bb_data_list, zone()); | 3485 table->Insert(key, bb_data_list, zone()); |
3472 } | 3486 } |
3473 } | 3487 } |
3474 | 3488 |
3475 for (int i = 0; i < bb->dominated_blocks()->length(); ++i) { | 3489 for (int i = 0; i < bb->dominated_blocks()->length(); ++i) { |
3476 EliminateRedundantBoundsChecks(bb->dominated_blocks()->at(i), table); | 3490 EliminateRedundantBoundsChecks(bb->dominated_blocks()->at(i), table); |
3477 } | 3491 } |
3478 | 3492 |
(...skipping 6077 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9556 } | 9570 } |
9557 } | 9571 } |
9558 | 9572 |
9559 #ifdef DEBUG | 9573 #ifdef DEBUG |
9560 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 9574 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
9561 if (allocator_ != NULL) allocator_->Verify(); | 9575 if (allocator_ != NULL) allocator_->Verify(); |
9562 #endif | 9576 #endif |
9563 } | 9577 } |
9564 | 9578 |
9565 } } // namespace v8::internal | 9579 } } // namespace v8::internal |
OLD | NEW |