1bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// Copyright 2013 the V8 project authors. All rights reserved.
2bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// Redistribution and use in source and binary forms, with or without
3bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// modification, are permitted provided that the following conditions are
4bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// met:
5bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org//
6bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org//     * Redistributions of source code must retain the above copyright
7bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org//       notice, this list of conditions and the following disclaimer.
8bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org//     * Redistributions in binary form must reproduce the above
9bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org//       copyright notice, this list of conditions and the following
10bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org//       disclaimer in the documentation and/or other materials provided
11bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org//       with the distribution.
12bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org//     * Neither the name of Google Inc. nor the names of its
13bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org//       contributors may be used to endorse or promote products derived
14bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org//       from this software without specific prior written permission.
15bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org//
16bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
28bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org#include "hydrogen-bce.h"
29bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
30bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.orgnamespace v8 {
31bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.orgnamespace internal {
32bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
33bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// We try to "factor up" HBoundsCheck instructions towards the root of the
34bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// dominator tree.
35bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// For now we handle checks where the index is like "exp + int32value".
36bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// If in the dominator tree we check "exp + v1" and later (dominated)
37bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// "exp + v2", if v2 <= v1 we can safely remove the second check, and if
38bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// v2 > v1 we can use v2 in the 1st check and again remove the second.
39bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// To do so we keep a dictionary of all checks where the key if the pair
40bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// "exp, length".
41bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// The class BoundsCheckKey represents this key.
42bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.orgclass BoundsCheckKey : public ZoneObject {
43bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org public:
44bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  HValue* IndexBase() const { return index_base_; }
45bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  HValue* Length() const { return length_; }
46bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
47bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  uint32_t Hash() {
48bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    return static_cast<uint32_t>(index_base_->Hashcode() ^ length_->Hashcode());
49bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  }
50bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
51bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  static BoundsCheckKey* Create(Zone* zone,
52bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                HBoundsCheck* check,
53bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                int32_t* offset) {
54bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    if (!check->index()->representation().IsSmiOrInteger32()) return NULL;
55bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
56bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    HValue* index_base = NULL;
57bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    HConstant* constant = NULL;
58bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    bool is_sub = false;
59bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
60bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    if (check->index()->IsAdd()) {
61bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      HAdd* index = HAdd::cast(check->index());
62bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      if (index->left()->IsConstant()) {
63bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        constant = HConstant::cast(index->left());
64bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        index_base = index->right();
65bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      } else if (index->right()->IsConstant()) {
66bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        constant = HConstant::cast(index->right());
67bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        index_base = index->left();
68bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      }
69bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    } else if (check->index()->IsSub()) {
70bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      HSub* index = HSub::cast(check->index());
71bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      is_sub = true;
72bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      if (index->left()->IsConstant()) {
73bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        constant = HConstant::cast(index->left());
74bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        index_base = index->right();
75bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      } else if (index->right()->IsConstant()) {
76bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        constant = HConstant::cast(index->right());
77bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        index_base = index->left();
78bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      }
79bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    }
80bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
81bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    if (constant != NULL && constant->HasInteger32Value()) {
82bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      *offset = is_sub ? - constant->Integer32Value()
83bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                       : constant->Integer32Value();
84bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    } else {
85bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      *offset = 0;
86bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      index_base = check->index();
87bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    }
88bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
89bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    return new(zone) BoundsCheckKey(index_base, check->length());
90bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  }
91bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
92bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org private:
93bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  BoundsCheckKey(HValue* index_base, HValue* length)
94bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    : index_base_(index_base),
95bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      length_(length) { }
96bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
97bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  HValue* index_base_;
98bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  HValue* length_;
99bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
100bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  DISALLOW_COPY_AND_ASSIGN(BoundsCheckKey);
101bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org};
102bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
103bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
104bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// Data about each HBoundsCheck that can be eliminated or moved.
105bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// It is the "value" in the dictionary indexed by "base-index, length"
106bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// (the key is BoundsCheckKey).
107bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// We scan the code with a dominator tree traversal.
108bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// Traversing the dominator tree we keep a stack (implemented as a singly
109bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// linked list) of "data" for each basic block that contains a relevant check
110bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// with the same key (the dictionary holds the head of the list).
111bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// We also keep all the "data" created for a given basic block in a list, and
112bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// use it to "clean up" the dictionary when backtracking in the dominator tree
113bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// traversal.
114bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// Doing this each dictionary entry always directly points to the check that
115bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// is dominating the code being examined now.
116bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// We also track the current "offset" of the index expression and use it to
117bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// decide if any check is already "covered" (so it can be removed) or not.
118bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.orgclass BoundsCheckBbData: public ZoneObject {
119bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org public:
120bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  BoundsCheckKey* Key() const { return key_; }
121bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  int32_t LowerOffset() const { return lower_offset_; }
122bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  int32_t UpperOffset() const { return upper_offset_; }
123bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  HBasicBlock* BasicBlock() const { return basic_block_; }
124bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  HBoundsCheck* LowerCheck() const { return lower_check_; }
125bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  HBoundsCheck* UpperCheck() const { return upper_check_; }
126bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  BoundsCheckBbData* NextInBasicBlock() const { return next_in_bb_; }
127bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  BoundsCheckBbData* FatherInDominatorTree() const { return father_in_dt_; }
128bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
129bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  bool OffsetIsCovered(int32_t offset) const {
130bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    return offset >= LowerOffset() && offset <= UpperOffset();
131bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  }
132bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
133bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  bool HasSingleCheck() { return lower_check_ == upper_check_; }
134bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
135bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // The goal of this method is to modify either upper_offset_ or
136bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // lower_offset_ so that also new_offset is covered (the covered
137bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // range grows).
138bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  //
139bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // The precondition is that new_check follows UpperCheck() and
140bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // LowerCheck() in the same basic block, and that new_offset is not
141bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // covered (otherwise we could simply remove new_check).
142bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  //
143bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // If HasSingleCheck() is true then new_check is added as "second check"
144bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // (either upper or lower; note that HasSingleCheck() becomes false).
145bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // Otherwise one of the current checks is modified so that it also covers
146bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // new_offset, and new_check is removed.
147bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  //
148bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // If the check cannot be modified because the context is unknown it
149bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // returns false, otherwise it returns true.
150bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  bool CoverCheck(HBoundsCheck* new_check,
151bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                  int32_t new_offset) {
152bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    ASSERT(new_check->index()->representation().IsSmiOrInteger32());
153bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    bool keep_new_check = false;
154bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
155bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    if (new_offset > upper_offset_) {
156bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      upper_offset_ = new_offset;
157bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      if (HasSingleCheck()) {
158bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        keep_new_check = true;
159bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        upper_check_ = new_check;
160bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      } else {
161bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        bool result = BuildOffsetAdd(upper_check_,
162bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                     &added_upper_index_,
163bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                     &added_upper_offset_,
164bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                     Key()->IndexBase(),
165bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                     new_check->index()->representation(),
166bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                     new_offset);
167bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        if (!result) return false;
168bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        upper_check_->ReplaceAllUsesWith(upper_check_->index());
169bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        upper_check_->SetOperandAt(0, added_upper_index_);
170bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      }
171bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    } else if (new_offset < lower_offset_) {
172bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      lower_offset_ = new_offset;
173bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      if (HasSingleCheck()) {
174bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        keep_new_check = true;
175bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        lower_check_ = new_check;
176bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      } else {
177bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        bool result = BuildOffsetAdd(lower_check_,
178bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                     &added_lower_index_,
179bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                     &added_lower_offset_,
180bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                     Key()->IndexBase(),
181bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                     new_check->index()->representation(),
182bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                     new_offset);
183bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        if (!result) return false;
184bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        lower_check_->ReplaceAllUsesWith(lower_check_->index());
185bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        lower_check_->SetOperandAt(0, added_lower_index_);
186bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      }
187bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    } else {
188bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      ASSERT(false);
189bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    }
190bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
191bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    if (!keep_new_check) {
192fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org      new_check->block()->graph()->isolate()->counters()->
193fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org          bounds_checks_eliminated()->Increment();
194bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      new_check->DeleteAndReplaceWith(new_check->ActualValue());
195bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    }
196bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
197bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    return true;
198bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  }
199bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
200bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  void RemoveZeroOperations() {
201bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    RemoveZeroAdd(&added_lower_index_, &added_lower_offset_);
202bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    RemoveZeroAdd(&added_upper_index_, &added_upper_offset_);
203bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  }
204bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
205bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  BoundsCheckBbData(BoundsCheckKey* key,
206bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                    int32_t lower_offset,
207bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                    int32_t upper_offset,
208bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                    HBasicBlock* bb,
209bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                    HBoundsCheck* lower_check,
210bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                    HBoundsCheck* upper_check,
211bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                    BoundsCheckBbData* next_in_bb,
212bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                    BoundsCheckBbData* father_in_dt)
213bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  : key_(key),
214bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    lower_offset_(lower_offset),
215bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    upper_offset_(upper_offset),
216bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    basic_block_(bb),
217bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    lower_check_(lower_check),
218bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    upper_check_(upper_check),
219bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    added_lower_index_(NULL),
220bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    added_lower_offset_(NULL),
221bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    added_upper_index_(NULL),
222bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    added_upper_offset_(NULL),
223bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    next_in_bb_(next_in_bb),
224bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    father_in_dt_(father_in_dt) { }
225bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
226bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org private:
227bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  BoundsCheckKey* key_;
228bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  int32_t lower_offset_;
229bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  int32_t upper_offset_;
230bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  HBasicBlock* basic_block_;
231bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  HBoundsCheck* lower_check_;
232bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  HBoundsCheck* upper_check_;
233bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  HInstruction* added_lower_index_;
234bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  HConstant* added_lower_offset_;
235bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  HInstruction* added_upper_index_;
236bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  HConstant* added_upper_offset_;
237bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  BoundsCheckBbData* next_in_bb_;
238bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  BoundsCheckBbData* father_in_dt_;
239bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
240bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // Given an existing add instruction and a bounds check it tries to
241bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // find the current context (either of the add or of the check index).
242bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  HValue* IndexContext(HInstruction* add, HBoundsCheck* check) {
243bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    if (add != NULL && add->IsAdd()) {
244bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      return HAdd::cast(add)->context();
245bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    }
246bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    if (check->index()->IsBinaryOperation()) {
247bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      return HBinaryOperation::cast(check->index())->context();
248bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    }
249bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    return NULL;
250bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  }
251bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
252bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // This function returns false if it cannot build the add because the
253bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  // current context cannot be determined.
254bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  bool BuildOffsetAdd(HBoundsCheck* check,
255bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                      HInstruction** add,
256bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                      HConstant** constant,
257bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                      HValue* original_value,
258bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                      Representation representation,
259bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                      int32_t new_offset) {
260bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    HValue* index_context = IndexContext(*add, check);
261bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    if (index_context == NULL) return false;
262bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
263d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org    Zone* zone = BasicBlock()->zone();
264d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org    HConstant* new_constant = HConstant::New(zone, index_context,
265d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org                                             new_offset, representation);
266bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    if (*add == NULL) {
267bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      new_constant->InsertBefore(check);
268d3c42109e5b85232d19beab8deeb24bdcbbf07f9danno@chromium.org      (*add) = HAdd::New(zone, index_context, original_value, new_constant);
269bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      (*add)->AssumeRepresentation(representation);
270bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      (*add)->InsertBefore(check);
271bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    } else {
272bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      new_constant->InsertBefore(*add);
273bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      (*constant)->DeleteAndReplaceWith(new_constant);
274bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    }
275bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    *constant = new_constant;
276bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    return true;
277bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  }
278bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
279bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  void RemoveZeroAdd(HInstruction** add, HConstant** constant) {
280bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    if (*add != NULL && (*add)->IsAdd() && (*constant)->Integer32Value() == 0) {
281bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      (*add)->DeleteAndReplaceWith(HAdd::cast(*add)->left());
282bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      (*constant)->DeleteAndReplaceWith(NULL);
283bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    }
284bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  }
285bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
286bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  DISALLOW_COPY_AND_ASSIGN(BoundsCheckBbData);
287bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org};
288bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
289bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
290bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.orgstatic bool BoundsCheckKeyMatch(void* key1, void* key2) {
291bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  BoundsCheckKey* k1 = static_cast<BoundsCheckKey*>(key1);
292bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  BoundsCheckKey* k2 = static_cast<BoundsCheckKey*>(key2);
293bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  return k1->IndexBase() == k2->IndexBase() && k1->Length() == k2->Length();
294bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org}
295bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
296bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
297bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.orgBoundsCheckTable::BoundsCheckTable(Zone* zone)
298bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    : ZoneHashMap(BoundsCheckKeyMatch, ZoneHashMap::kDefaultHashMapCapacity,
299bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                  ZoneAllocationPolicy(zone)) { }
300bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
301bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
302bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.orgBoundsCheckBbData** BoundsCheckTable::LookupOrInsert(BoundsCheckKey* key,
303bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                                     Zone* zone) {
304bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  return reinterpret_cast<BoundsCheckBbData**>(
305bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      &(Lookup(key, key->Hash(), true, ZoneAllocationPolicy(zone))->value));
306bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org}
307bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
308bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
309bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.orgvoid BoundsCheckTable::Insert(BoundsCheckKey* key,
310bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                              BoundsCheckBbData* data,
311bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                              Zone* zone) {
312bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  Lookup(key, key->Hash(), true, ZoneAllocationPolicy(zone))->value = data;
313bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org}
314bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
315bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
316bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.orgvoid BoundsCheckTable::Delete(BoundsCheckKey* key) {
317bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  Remove(key, key->Hash());
318bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org}
319bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
320bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
321c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.orgclass HBoundsCheckEliminationState {
322c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org public:
323c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org  HBasicBlock* block_;
324c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org  BoundsCheckBbData* bb_data_list_;
325c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org  int index_;
326c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org};
327c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org
328c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org
329bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// Eliminates checks in bb and recursively in the dominated blocks.
330bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// Also replace the results of check instructions with the original value, if
331bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// the result is used. This is safe now, since we don't do code motion after
332bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// this point. It enables better register allocation since the value produced
333bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// by check instructions is really a copy of the original value.
334bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.orgvoid HBoundsCheckEliminationPhase::EliminateRedundantBoundsChecks(
335c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org    HBasicBlock* entry) {
336c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org  // Allocate the stack.
337c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org  HBoundsCheckEliminationState* stack =
338c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org    zone()->NewArray<HBoundsCheckEliminationState>(graph()->blocks()->length());
339c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org
340c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org  // Explicitly push the entry block.
341c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org  stack[0].block_ = entry;
342c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org  stack[0].bb_data_list_ = PreProcessBlock(entry);
343c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org  stack[0].index_ = 0;
344c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org  int stack_depth = 1;
345c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org
346c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org  // Implement depth-first traversal with a stack.
347c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org  while (stack_depth > 0) {
348c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org    int current = stack_depth - 1;
349c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org    HBoundsCheckEliminationState* state = &stack[current];
350c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org    const ZoneList<HBasicBlock*>* children = state->block_->dominated_blocks();
351c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org
352c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org    if (state->index_ < children->length()) {
353c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org      // Recursively visit children blocks.
354c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org      HBasicBlock* child = children->at(state->index_++);
355c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org      int next = stack_depth++;
356c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org      stack[next].block_ = child;
357c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org      stack[next].bb_data_list_ = PreProcessBlock(child);
358c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org      stack[next].index_ = 0;
359c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org    } else {
360c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org      // Finished with all children; post process the block.
361c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org      PostProcessBlock(state->block_, state->bb_data_list_);
362c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org      stack_depth--;
363c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org    }
364c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org  }
365c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org}
366c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org
367c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org
368c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.orgBoundsCheckBbData* HBoundsCheckEliminationPhase::PreProcessBlock(
369bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    HBasicBlock* bb) {
370bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  BoundsCheckBbData* bb_data_list = NULL;
371bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
372bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  for (HInstructionIterator it(bb); !it.Done(); it.Advance()) {
373bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    HInstruction* i = it.Current();
374bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    if (!i->IsBoundsCheck()) continue;
375bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
376bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    HBoundsCheck* check = HBoundsCheck::cast(i);
377bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    int32_t offset;
378bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    BoundsCheckKey* key =
379bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org        BoundsCheckKey::Create(zone(), check, &offset);
380bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    if (key == NULL) continue;
381bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    BoundsCheckBbData** data_p = table_.LookupOrInsert(key, zone());
382bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    BoundsCheckBbData* data = *data_p;
383bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    if (data == NULL) {
384bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      bb_data_list = new(zone()) BoundsCheckBbData(key,
385bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                                   offset,
386bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                                   offset,
387bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                                   bb,
388bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                                   check,
389bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                                   check,
390bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                                   bb_data_list,
391bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                                   NULL);
392bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      *data_p = bb_data_list;
393bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    } else if (data->OffsetIsCovered(offset)) {
394fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org      bb->graph()->isolate()->counters()->
395fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org          bounds_checks_eliminated()->Increment();
396bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      check->DeleteAndReplaceWith(check->ActualValue());
397bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    } else if (data->BasicBlock() != bb ||
398bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org               !data->CoverCheck(check, offset)) {
399bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      // If the check is in the current BB we try to modify it by calling
400bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      // "CoverCheck", but if also that fails we record the current offsets
401bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      // in a new data instance because from now on they are covered.
402bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      int32_t new_lower_offset = offset < data->LowerOffset()
403bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org          ? offset
404bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org          : data->LowerOffset();
405bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      int32_t new_upper_offset = offset > data->UpperOffset()
406bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org          ? offset
407bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org          : data->UpperOffset();
408bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      bb_data_list = new(zone()) BoundsCheckBbData(key,
409bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                                   new_lower_offset,
410bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                                   new_upper_offset,
411bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                                   bb,
412bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                                   data->LowerCheck(),
413bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                                   data->UpperCheck(),
414bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                                   bb_data_list,
415bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org                                                   data);
416bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      table_.Insert(key, bb_data_list, zone());
417bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    }
418bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  }
419bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
420c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org  return bb_data_list;
421c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org}
422c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org
423bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
424c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.orgvoid HBoundsCheckEliminationPhase::PostProcessBlock(
425c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org    HBasicBlock* block, BoundsCheckBbData* data) {
426c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org  while (data != NULL) {
427bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    data->RemoveZeroOperations();
428bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    if (data->FatherInDominatorTree()) {
429bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      table_.Insert(data->Key(), data->FatherInDominatorTree(), zone());
430bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    } else {
431bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org      table_.Delete(data->Key());
432bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org    }
433c7528a8f3c24df07dd43ff79a22d71517f686b6cdanno@chromium.org    data = data->NextInBasicBlock();
434bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org  }
435bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org}
436bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org
437bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org} }  // namespace v8::internal
438