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

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: HOptimizedGraphBuilder::BuildArrayIndexOf() 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 | « src/hydrogen.h ('k') | 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..49fd879bdc4f397062db5cf791668a2658cebf42 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -8032,6 +8032,43 @@ 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();
+ Drop(1); // Drop function.
+
+ ArrayIndexOfMode mode = (id == kArrayIndexOf)
+ ? kFirstIndexOf : kLastIndexOf;
+ HValue* index = BuildArrayIndexOf(receiver, search_element, kind, mode);
+
+ if (!ast_context()->IsEffect()) Push(index);
+ 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;
@@ -8324,6 +8361,148 @@ void HOptimizedGraphBuilder::BuildArrayCall(Expression* expression,
}
+HValue* HOptimizedGraphBuilder::BuildArrayIndexOf(HValue* receiver,
+ HValue* search_element,
+ ElementsKind kind,
+ ArrayIndexOfMode mode) {
+ ASSERT(IsFastElementsKind(kind));
+
+ NoObservableSideEffectsScope no_effects(this);
+
+ HValue* elements = AddLoadElements(receiver);
+ HValue* length = AddLoadArrayLength(receiver, kind);
+
+ HValue* initial;
+ HValue* terminating;
+ Token::Value token;
+ LoopBuilder::Direction direction;
+ if (mode == kFirstIndexOf) {
+ initial = graph()->GetConstant0();
+ terminating = length;
+ token = Token::LT;
+ direction = LoopBuilder::kPostIncrement;
+ } else {
+ ASSERT_EQ(kLastIndexOf, mode);
+ initial = length;
+ terminating = graph()->GetConstant0();
+ token = Token::GTE;
+ direction = LoopBuilder::kPreDecrement;
+ }
+
+ Push(graph()->GetConstantMinus1());
+ if (IsFastDoubleElementsKind(kind) || IsFastSmiElementsKind(kind)) {
+ LoopBuilder loop(this, context(), direction);
+ {
+ HValue* 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();
+ {
+ 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);
+ {
+ HValue* 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();
+ {
+ Drop(1);
+ Push(index);
+ loop.Break();
+ }
+ if_issame.End();
+ }
+ loop.EndBody();
+ }
+ if_isstring.Else();
+ {
+ IfBuilder if_isheapnumber(this);
+ if_isheapnumber.IfNot<HIsSmiAndBranch>(search_element);
+ HCompareMap* isheapnumber = if_isheapnumber.AndIf<HCompareMap>(
+ search_element, isolate()->factory()->heap_number_map());
+ if_isheapnumber.Then();
+ {
+ HValue* search_number = Add<HLoadNamedField>(
+ search_element, isheapnumber,
+ HObjectAccess::ForHeapNumberValue());
+ LoopBuilder loop(this, context(), direction);
+ {
+ HValue* index = loop.BeginBody(initial, terminating, token);
+ HValue* element = AddUncasted<HLoadKeyed>(
+ elements, index, static_cast<HValue*>(NULL),
+ kind, ALLOW_RETURN_HOLE);
+ IfBuilder if_issame(this);
+ HCompareMap* issame = if_issame.If<HCompareMap>(
+ element, isolate()->factory()->heap_number_map());
+ if_issame.And();
+ HValue* number = Add<HLoadNamedField>(
+ element, issame, HObjectAccess::ForHeapNumberValue());
+ if_issame.If<HCompareNumericAndBranch>(
+ number, search_number, Token::EQ_STRICT);
+ if_issame.Then();
+ {
+ Drop(1);
+ Push(index);
+ loop.Break();
+ }
+ if_issame.End();
+ }
+ loop.EndBody();
+ }
+ if_isheapnumber.Else();
+ {
+ LoopBuilder loop(this, context(), direction);
+ {
+ HValue* 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();
+ {
+ Drop(1);
+ Push(index);
+ loop.Break();
+ }
+ if_issame.End();
+ }
+ loop.EndBody();
+ }
+ if_isheapnumber.End();
+ }
+ if_isstring.End();
+ }
+
+ return Pop();
+}
+
+
bool HOptimizedGraphBuilder::TryHandleArrayCall(Call* expr, HValue* function) {
if (!array_function().is_identical_to(expr->target())) {
return false;
« no previous file with comments | « src/hydrogen.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698