Chromium Code Reviews| Index: src/hydrogen.cc |
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
| index c836dc21653129de5d7255a3c8d8b2e9c63e71c0..b61da6aac026807c60e688c51d4ae93f76b4e890 100644 |
| --- a/src/hydrogen.cc |
| +++ b/src/hydrogen.cc |
| @@ -8032,6 +8032,143 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( |
| ast_context()->ReturnValue(result); |
| return true; |
| } |
| + case kArrayIndexOf: |
| + case kArrayLastIndexOf: { |
| + if (receiver_map.is_null()) return false; |
| + if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false; |
| + ElementsKind kind = receiver_map->elements_kind(); |
| + if (!IsFastElementsKind(kind)) return false; |
| + if (receiver_map->is_observed()) return false; |
| + if (argument_count != 2) return false; |
| + ASSERT(receiver_map->is_extensible()); |
| + |
| + // If there may be elements accessors in the prototype chain, the fast |
| + // inlined version can't be used. |
| + if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false; |
| + |
| + // If there currently can be no elements accessors on the prototype chain, |
| + // it doesn't mean that there won't be any later. Install a full prototype |
| + // chain check to trap element accessors being installed on the prototype |
| + // chain, which would cause elements to go to dictionary mode and result |
| + // in a map change. |
| + BuildCheckPrototypeMaps( |
| + handle(JSObject::cast(receiver_map->prototype()), isolate()), |
| + Handle<JSObject>::null()); |
| + |
| + HValue* search_element = Pop(); |
| + HValue* receiver = Pop(); |
| + HValue* index; |
| + Drop(1); // Drop function. |
| + |
| + { |
|
mvstanton
2014/06/02 11:43:44
How about put this in a function, BuildArrayIndexO
Benedikt Meurer
2014/06/02 12:08:16
Done.
|
| + NoObservableSideEffectsScope scope(this); |
| + |
| + HValue* elements = AddLoadElements(receiver); |
| + HValue* length = AddLoadArrayLength(receiver, kind); |
| + |
| + HValue* initial; |
| + HValue* terminating; |
| + Token::Value token; |
| + LoopBuilder::Direction direction; |
| + if (id == kArrayIndexOf) { |
| + initial = graph()->GetConstant0(); |
| + terminating = length; |
| + token = Token::LT; |
| + direction = LoopBuilder::kPostIncrement; |
| + } else { |
| + ASSERT_EQ(kArrayLastIndexOf, id); |
| + initial = length; |
| + terminating = graph()->GetConstant0(); |
| + token = Token::GTE; |
| + direction = LoopBuilder::kPreDecrement; |
| + } |
| + |
| + if (!ast_context()->IsEffect()) Push(graph()->GetConstantMinus1()); |
| + if (IsFastDoubleElementsKind(kind) || |
| + IsFastSmiElementsKind(kind)) { |
| + LoopBuilder loop(this, context(), direction); |
| + { |
| + index = loop.BeginBody(initial, terminating, token); |
| + HValue* element = AddUncasted<HLoadKeyed>( |
| + elements, index, static_cast<HValue*>(NULL), |
| + kind, ALLOW_RETURN_HOLE); |
| + IfBuilder if_issame(this); |
| + if (IsFastDoubleElementsKind(kind)) { |
| + if_issame.If<HCompareNumericAndBranch>( |
| + element, search_element, Token::EQ_STRICT); |
| + } else { |
| + if_issame.If<HCompareObjectEqAndBranch>(element, search_element); |
| + } |
| + if_issame.Then(); |
| + { |
| + if (!ast_context()->IsEffect()) { |
| + Drop(1); |
| + Push(index); |
| + } |
| + loop.Break(); |
| + } |
| + if_issame.End(); |
| + } |
| + loop.EndBody(); |
| + } else { |
| + IfBuilder if_isstring(this); |
| + if_isstring.If<HIsStringAndBranch>(search_element); |
| + if_isstring.Then(); |
| + { |
| + LoopBuilder loop(this, context(), direction); |
| + { |
| + index = loop.BeginBody(initial, terminating, token); |
| + HValue* element = AddUncasted<HLoadKeyed>( |
| + elements, index, static_cast<HValue*>(NULL), |
| + kind, ALLOW_RETURN_HOLE); |
| + IfBuilder if_issame(this); |
| + if_issame.If<HIsStringAndBranch>(element); |
| + if_issame.AndIf<HStringCompareAndBranch>( |
| + element, search_element, Token::EQ_STRICT); |
| + if_issame.Then(); |
| + { |
| + if (!ast_context()->IsEffect()) { |
| + Drop(1); |
| + Push(index); |
| + } |
| + loop.Break(); |
| + } |
| + if_issame.End(); |
| + } |
| + loop.EndBody(); |
| + } |
| + if_isstring.Else(); |
| + { |
| + LoopBuilder loop(this, context(), direction); |
| + { |
| + index = loop.BeginBody(initial, terminating, token); |
| + HValue* element = AddUncasted<HLoadKeyed>( |
| + elements, index, static_cast<HValue*>(NULL), |
| + kind, ALLOW_RETURN_HOLE); |
| + IfBuilder if_issame(this); |
| + if_issame.If<HCompareObjectEqAndBranch>(element, search_element); |
| + if_issame.Then(); |
| + { |
| + if (!ast_context()->IsEffect()) { |
| + Drop(1); |
| + Push(index); |
| + } |
| + loop.Break(); |
| + } |
| + if_issame.End(); |
| + } |
| + loop.EndBody(); |
| + } |
| + if_isstring.End(); |
| + } |
| + } |
|
mvstanton
2014/06/02 11:43:44
function ends here, postcondition being that in no
|
| + |
| + index = ast_context()->IsEffect() ? graph()->GetConstant0() : Top(); |
| + Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
| + if (!ast_context()->IsEffect()) Drop(1); |
| + ast_context()->ReturnValue(index); |
| + return true; |
| + } |
| default: |
| // Not yet supported for inlining. |
| break; |