Reviewers: Toon Verwaest,
Message:
Hi Toon, here is the issue we worked on, thanks!
--Michael
Description:
Fix for V8 issue 2795: Check fails with deopt for
mjsunit/array-store-and-grow
(https://code.google.com/p/v8/issues/detail?id=2795)
The reason is when allocating and building arrays in hydrogen we need to
ensure
we do any int32-to-smi conversions BEFORE the allocation. These conversions
can
at least theoretically deoptimize. If this happens before all the fields of
the
newly allocated object are filled in, we will have a corrupted heap.
BUG=
Please review this at https://codereview.chromium.org/20726002/
SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files:
M src/hydrogen-instructions.h
M src/hydrogen.cc
Index: src/hydrogen-instructions.h
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index
bf59159164c53b4e41ae52ee2d48d76625017a1b..e6a618375a0db024bb7d25e5cb71d7f8404a3843
100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -5583,9 +5583,11 @@ class HObjectAccess {
static HObjectAccess ForArrayLength(ElementsKind elements_kind) {
return HObjectAccess(
- kArrayLengths, JSArray::kLengthOffset,
- IsFastElementsKind(elements_kind) && FLAG_track_fields ?
- Representation::Smi() : Representation::Tagged());
+ kArrayLengths,
+ JSArray::kLengthOffset,
+ IsFastElementsKind(elements_kind) &&
+ FLAG_track_fields
+ ? Representation::Smi() : Representation::Tagged());
}
static HObjectAccess ForAllocationSiteTransitionInfo() {
@@ -5598,9 +5600,9 @@ class HObjectAccess {
static HObjectAccess ForFixedArrayLength() {
return HObjectAccess(
- kArrayLengths, FixedArray::kLengthOffset,
- FLAG_track_fields ?
- Representation::Smi() : Representation::Tagged());
+ kArrayLengths,
+ FixedArray::kLengthOffset,
+ FLAG_track_fields ? Representation::Smi() :
Representation::Tagged());
}
static HObjectAccess ForPropertiesPointer() {
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index
853c0c0aafd321cb8b7163403a09cd5daeedda04..0433951a678a26f50c6a9a285eb0d530ae78de37
100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -1078,8 +1078,16 @@ HValue*
HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
HValue* context = environment()->LookupContext();
- HValue* new_capacity = BuildNewElementsCapacity(context, key);
+ HValue* max_gap =
Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap));
+ HValue* max_capacity = AddInstruction(
+ HAdd::New(zone, context, current_capacity, max_gap));
+ IfBuilder key_checker(this);
+ key_checker.If<HCompareNumericAndBranch>(key, max_capacity, Token::LT);
+ key_checker.Then();
+ key_checker.ElseDeopt();
+ key_checker.End();
+ HValue* new_capacity = BuildNewElementsCapacity(context, key);
HValue* new_elements = BuildGrowElementsCapacity(object, elements,
kind, kind, length,
new_capacity);
@@ -1337,6 +1345,9 @@ HValue*
HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader(
HValue* context,
ElementsKind kind,
HValue* capacity) {
+ // The HForceRepresentation is to prevent possible deopt on int-smi
+ // conversion after allocation but before the new object fields are set.
+ capacity = Add<HForceRepresentation>(capacity, Representation::Smi());
HValue* new_elements = BuildAllocateElements(context, kind, capacity);
BuildInitializeElementsHeader(new_elements, kind, capacity);
return new_elements;
@@ -1474,7 +1485,6 @@ HValue*
HGraphBuilder::BuildNewElementsCapacity(HValue* context,
HValue* half_old_capacity =
AddInstruction(HShr::New(zone, context, old_capacity,
graph_->GetConstant1()));
- half_old_capacity->ClearFlag(HValue::kCanOverflow);
HValue* new_capacity = AddInstruction(
HAdd::New(zone, context, half_old_capacity, old_capacity));
@@ -1497,8 +1507,6 @@ void HGraphBuilder::BuildNewSpaceArrayCheck(HValue*
length, ElementsKind kind) {
int max_size = heap->MaxRegularSpaceAllocationSize() / element_size;
max_size -= JSArray::kSize / element_size;
HConstant* max_size_constant = Add<HConstant>(max_size);
- // Since we're forcing Integer32 representation for this HBoundsCheck,
- // there's no need to Smi-check the index.
Add<HBoundsCheck>(length, max_size_constant);
}
@@ -1927,6 +1935,14 @@ HValue*
HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes,
bool fill_with_hole) {
HValue* context = builder()->environment()->LookupContext();
+ // These HForceRepresentations are because we store these as fields in
the
+ // objects we construct, and an int32-to-smi HChange could deopt. Accept
+ // the deopt possibility now, before allocation occurs.
+ capacity = builder()->Add<HForceRepresentation>(capacity,
+ Representation::Smi());
+ length_field = builder()->Add<HForceRepresentation>(length_field,
+
Representation::Smi());
+
// Allocate (dealing with failure appropriately)
HAllocate::Flags flags = HAllocate::DefaultFlags(kind_);
HAllocate* new_object = builder()->Add<HAllocate>(context, size_in_bytes,
--
--
v8-dev mailing list
[email protected]
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 [email protected].
For more options, visit https://groups.google.com/groups/opt_out.