Reviewers: danno,

Message:
Hi Danno, here is the fix we discussed. Perhaps the overflow check is "overkill"
in the HStoreKeyed case? PTAL,
--Michael

Description:
Clusterfuzz identified overflow check needed in dehoisting.

BUG=380092
R=da...@chromium.org
LOG=N

Please review this at https://codereview.chromium.org/315593002/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files (+28, -25 lines):
  M src/hydrogen-dehoist.cc
  M src/hydrogen-instructions.h
  A + test/mjsunit/regress/regress-380092.js


Index: src/hydrogen-dehoist.cc
diff --git a/src/hydrogen-dehoist.cc b/src/hydrogen-dehoist.cc
index e8008231ad3f22feaba64fbe9220bcd6c656a0ae..859b9eca8f39052be325de2467c90c8573786aa1 100644
--- a/src/hydrogen-dehoist.cc
+++ b/src/hydrogen-dehoist.cc
@@ -28,15 +28,17 @@ static void DehoistArrayIndex(ArrayInstructionInterface* array_operation) {
   if (!constant->HasInteger32Value()) return;
   int32_t sign = binary_operation->IsSub() ? -1 : 1;
   int32_t value = constant->Integer32Value() * sign;
-  // We limit offset values to 30 bits because we want to avoid the risk of
-  // overflows when the offset is added to the object header size.
- if (value >= 1 << array_operation->MaxBaseOffsetBits() || value < 0) return;
+  if (value < 0) return;
+  uint32_t uvalue = static_cast<uint32_t>(value) <<
+      ElementsKindToShiftSize(array_operation->elements_kind());
+ // Protect against overflows when the offset is added to the object header
+  // size.
+  if (!array_operation->CanIncreaseBaseOffset(uvalue)) return;
   array_operation->SetKey(subexpression);
   if (binary_operation->HasNoUses()) {
     binary_operation->DeleteAndReplaceWith(NULL);
   }
-  value <<= ElementsKindToShiftSize(array_operation->elements_kind());
-  array_operation->IncreaseBaseOffset(static_cast<uint32_t>(value));
+  array_operation->IncreaseBaseOffset(uvalue);
   array_operation->SetDehoisted(true);
 }

Index: src/hydrogen-instructions.h
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index 05b31162af5730e4b83bb5844ed1aad40615f823..d106084a86c3f939267f02f4595ce26ca21f51f4 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -6426,8 +6426,8 @@ class ArrayInstructionInterface {
   virtual HValue* GetKey() = 0;
   virtual void SetKey(HValue* key) = 0;
   virtual ElementsKind elements_kind() const = 0;
-  virtual void IncreaseBaseOffset(uint32_t base_offset) = 0;
-  virtual int MaxBaseOffsetBits() = 0;
+  virtual bool CanIncreaseBaseOffset(uint32_t increase_by_value) = 0;
+  virtual void IncreaseBaseOffset(uint32_t increase_by_value) = 0;
   virtual bool IsDehoisted() = 0;
   virtual void SetDehoisted(bool is_dehoisted) = 0;
   virtual ~ArrayInstructionInterface() { }
@@ -6474,12 +6474,13 @@ class HLoadKeyed V8_FINAL
   }
   bool HasDependency() const { return OperandAt(0) != OperandAt(2); }
   uint32_t base_offset() { return BaseOffsetField::decode(bit_field_); }
-  void IncreaseBaseOffset(uint32_t base_offset) {
-    base_offset += BaseOffsetField::decode(bit_field_);
-    bit_field_ = BaseOffsetField::update(bit_field_, base_offset);
+  bool CanIncreaseBaseOffset(uint32_t increase_by_value) {
+    increase_by_value += BaseOffsetField::decode(bit_field_);
+    return BaseOffsetField::is_valid(increase_by_value);
   }
-  virtual int MaxBaseOffsetBits() {
-    return kBitsForBaseOffset;
+  void IncreaseBaseOffset(uint32_t increase_by_value) {
+    increase_by_value += BaseOffsetField::decode(bit_field_);
+    bit_field_ = BaseOffsetField::update(bit_field_, increase_by_value);
   }
   HValue* GetKey() { return key(); }
   void SetKey(HValue* key) { SetOperandAt(1, key); }
@@ -6935,11 +6936,13 @@ class HStoreKeyed V8_FINAL
   StoreFieldOrKeyedMode store_mode() const { return store_mode_; }
   ElementsKind elements_kind() const { return elements_kind_; }
   uint32_t base_offset() { return base_offset_; }
-  void IncreaseBaseOffset(uint32_t base_offset) {
-    base_offset_ += base_offset;
+  bool CanIncreaseBaseOffset(uint32_t increase_by_value) {
+    // unsigned integer addition "wraps around."
+    uint32_t result = increase_by_value + base_offset_;
+    return result >= base_offset_ && result >= increase_by_value;
   }
-  virtual int MaxBaseOffsetBits() {
-    return 31 - ElementsKindToShiftSize(elements_kind_);
+  void IncreaseBaseOffset(uint32_t increase_by_value) {
+    base_offset_ += increase_by_value;
   }
   HValue* GetKey() { return key(); }
   void SetKey(HValue* key) { SetOperandAt(1, key); }
Index: test/mjsunit/regress/regress-380092.js
diff --git a/test/mjsunit/regress/regress-alloc-smi-check.js b/test/mjsunit/regress/regress-380092.js
similarity index 56%
copy from test/mjsunit/regress/regress-alloc-smi-check.js
copy to test/mjsunit/regress/regress-380092.js
index 295048a13ef862ceb21939de104e7968dd7772da..a7634355ca5d0db9a867cb691b05129b984911f8 100644
--- a/test/mjsunit/regress/regress-alloc-smi-check.js
+++ b/test/mjsunit/regress/regress-380092.js
@@ -1,16 +1,14 @@
 // Copyright 2014 the V8 project authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
-//
-// Flags: --allow-natives-syntax

-var x = {};
+// Flags: --allow-natives-syntax

-function f(a) {
-  a[200000000] = x;
+function many_hoist(o, index) {
+  return o[index + 33554427];
 }

-f(new Array(100000));
-f([]);
-%OptimizeFunctionOnNextCall(f);
-f([]);
+var obj = {};
+many_hoist(obj, 0);
+%OptimizeFunctionOnNextCall(many_hoist);
+many_hoist(obj, 5);


--
--
v8-dev mailing list
v8-dev@googlegroups.com
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to v8-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to