Index: src/code-stubs-hydrogen.cc |
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc |
index 68c864176b7b4913011f18eda4ae9328955f11df..a35da69f59c6590b9fac1912d068fedf69076148 100644 |
--- a/src/code-stubs-hydrogen.cc |
+++ b/src/code-stubs-hydrogen.cc |
@@ -1113,6 +1113,86 @@ Handle<Code> ElementsTransitionAndStoreStub::GenerateCode() { |
} |
+template <> |
+HValue* CodeStubGraphBuilder<ArrayShiftStub>::BuildCodeStub() { |
+ HValue* receiver = GetParameter(ArrayShiftStub::kReceiver); |
+ ElementsKind kind = casted_stub()->kind(); |
+ |
+ // We may use double registers for copying. |
+ if (IsFastDoubleElementsKind(kind)) info()->MarkAsSavesCallerDoubles(); |
+ |
+ HValue* length = Add<HLoadNamedField>( |
+ receiver, static_cast<HValue*>(NULL), |
+ HObjectAccess::ForArrayLength(kind)); |
+ |
+ IfBuilder if_lengthiszero(this); |
+ HValue* lengthiszero = if_lengthiszero.If<HCompareNumericAndBranch>( |
+ length, graph()->GetConstant0(), Token::EQ); |
+ if_lengthiszero.Then(); |
+ { |
+ Push(graph()->GetConstantUndefined()); |
+ } |
+ if_lengthiszero.Else(); |
+ { |
+ // Check if array length is below threshold. |
+ IfBuilder if_inline(this); |
+ if_inline.If<HCompareNumericAndBranch>( |
+ length, Add<HConstant>(ArrayShiftStub::kInlineThreshold), Token::LTE); |
+ if_inline.Then(); |
+ if_inline.ElseDeopt("Array length exceeds threshold"); |
+ if_inline.End(); |
+ |
+ // We cannot handle copy-on-write backing stores here. |
+ HValue* elements = AddLoadElements(receiver); |
+ if (IsFastSmiOrObjectElementsKind(kind)) { |
+ Add<HCheckMaps>(elements, isolate()->factory()->fixed_array_map()); |
+ } |
+ |
+ // Remember the result. |
+ Push(AddElementAccess(elements, graph()->GetConstant0(), NULL, |
+ lengthiszero, kind, LOAD)); |
+ |
+ // Compute the new length. |
+ HValue* new_length = AddUncasted<HSub>(length, graph()->GetConstant1()); |
+ new_length->ClearFlag(HValue::kCanOverflow); |
+ |
+ // Copy the remaining elements. |
+ LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement); |
+ { |
+ HValue* new_key = loop.BeginBody( |
+ graph()->GetConstant0(), new_length, Token::LT); |
+ HValue* key = AddUncasted<HAdd>(new_key, graph()->GetConstant1()); |
+ key->ClearFlag(HValue::kCanOverflow); |
+ HValue* element = AddUncasted<HLoadKeyed>( |
+ elements, key, lengthiszero, kind, ALLOW_RETURN_HOLE); |
+ HStoreKeyed* store = Add<HStoreKeyed>(elements, new_key, element, kind); |
+ store->SetFlag(HValue::kAllowUndefinedAsNaN); |
+ } |
+ loop.EndBody(); |
+ |
+ // Put a hole at the end. |
+ HValue* hole = IsFastSmiOrObjectElementsKind(kind) |
+ ? Add<HConstant>(isolate()->factory()->the_hole_value()) |
+ : Add<HConstant>(FixedDoubleArray::hole_nan_as_double()); |
+ if (IsFastSmiOrObjectElementsKind(kind)) kind = FAST_HOLEY_ELEMENTS; |
+ Add<HStoreKeyed>(elements, new_length, hole, kind, INITIALIZING_STORE); |
+ |
+ // Remember new length. |
+ Add<HStoreNamedField>( |
+ receiver, HObjectAccess::ForArrayLength(kind), |
+ new_length, STORE_TO_INITIALIZED_ENTRY); |
+ } |
+ if_lengthiszero.End(); |
+ |
+ return Pop(); |
+} |
+ |
+ |
+Handle<Code> ArrayShiftStub::GenerateCode() { |
+ return DoGenerateCode(this); |
+} |
+ |
+ |
void CodeStubGraphBuilderBase::BuildCheckAndInstallOptimizedCode( |
HValue* js_function, |
HValue* native_context, |