| 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 |