Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(384)

Unified Diff: src/hydrogen.cc

Issue 308793012: Inline fast path for Array.indexOf() and Array.lastIndexOf(). (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/objects.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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;
« no previous file with comments | « no previous file | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698