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

Side by Side Diff: src/hydrogen.cc

Issue 10698125: Fixed array bounds check elimination (Chromium issue 132114). (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « src/flag-definitions.h ('k') | test/mjsunit/array-bounds-check-removal.js » ('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 // 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
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
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
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
OLDNEW
« no previous file with comments | « src/flag-definitions.h ('k') | test/mjsunit/array-bounds-check-removal.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698