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; |