Chromium Code Reviews| Index: src/hydrogen.cc |
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
| index 851a05d6f8082126eeb824c89c3b27216c754162..c836dc21653129de5d7255a3c8d8b2e9c63e71c0 100644 |
| --- a/src/hydrogen.cc |
| +++ b/src/hydrogen.cc |
| @@ -7940,13 +7940,96 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( |
| handle(JSObject::cast(receiver_map->prototype()), isolate()), |
| Handle<JSObject>::null()); |
| + // Threshold for fast inlined Array.shift(). |
| + HConstant* inline_threshold = Add<HConstant>(static_cast<int32_t>(16)); |
| + |
| Drop(expr->arguments()->length()); |
| HValue* receiver = Pop(); |
| - Drop(1); // function |
| + HValue* function = Pop(); |
| + HValue* result; |
| + |
| + { |
|
Yang
2014/06/02 06:57:01
Could we have a BuildArrayShift instead of having
Benedikt Meurer
2014/06/02 07:02:12
As discussed offline: Leaving it here for consiste
|
| + NoObservableSideEffectsScope scope(this); |
| + |
| + 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(); |
| + { |
| + if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined()); |
| + } |
| + if_lengthiszero.Else(); |
| + { |
| + HValue* elements = AddLoadElements(receiver); |
| + |
| + // Check if we can use the fast inlined Array.shift(). |
| + IfBuilder if_inline(this); |
| + if_inline.If<HCompareNumericAndBranch>( |
| + length, inline_threshold, Token::LTE); |
| + if (IsFastSmiOrObjectElementsKind(kind)) { |
| + // We cannot handle copy-on-write backing stores here. |
| + if_inline.AndIf<HCompareMap>( |
| + elements, isolate()->factory()->fixed_array_map()); |
| + } |
| + if_inline.Then(); |
| + { |
| + // Remember the result. |
| + if (!ast_context()->IsEffect()) { |
| + 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); |
| - receiver = AddCheckMap(receiver, receiver_map); |
| - HInstruction* result = NewUncasted<HArrayShift>(receiver, kind); |
| - ast_context()->ReturnInstruction(result, expr->id()); |
| + // 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_inline.Else(); |
| + { |
| + Add<HPushArguments>(receiver); |
| + result = Add<HCallJSFunction>(function, 1, true); |
| + if (!ast_context()->IsEffect()) Push(result); |
| + } |
| + if_inline.End(); |
| + } |
| + if_lengthiszero.End(); |
| + } |
| + result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top(); |
| + Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
| + if (!ast_context()->IsEffect()) Drop(1); |
| + ast_context()->ReturnValue(result); |
| return true; |
| } |
| default: |