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

Side by Side 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, 6 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | src/objects.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "hydrogen.h" 5 #include "hydrogen.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "v8.h" 9 #include "v8.h"
10 #include "allocation-site-scopes.h" 10 #include "allocation-site-scopes.h"
(...skipping 8014 matching lines...) Expand 10 before | Expand all | Expand 10 after
8025 if_inline.End(); 8025 if_inline.End();
8026 } 8026 }
8027 if_lengthiszero.End(); 8027 if_lengthiszero.End();
8028 } 8028 }
8029 result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top(); 8029 result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
8030 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); 8030 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
8031 if (!ast_context()->IsEffect()) Drop(1); 8031 if (!ast_context()->IsEffect()) Drop(1);
8032 ast_context()->ReturnValue(result); 8032 ast_context()->ReturnValue(result);
8033 return true; 8033 return true;
8034 } 8034 }
8035 case kArrayIndexOf:
8036 case kArrayLastIndexOf: {
8037 if (receiver_map.is_null()) return false;
8038 if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
8039 ElementsKind kind = receiver_map->elements_kind();
8040 if (!IsFastElementsKind(kind)) return false;
8041 if (receiver_map->is_observed()) return false;
8042 if (argument_count != 2) return false;
8043 ASSERT(receiver_map->is_extensible());
8044
8045 // If there may be elements accessors in the prototype chain, the fast
8046 // inlined version can't be used.
8047 if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
8048
8049 // If there currently can be no elements accessors on the prototype chain,
8050 // it doesn't mean that there won't be any later. Install a full prototype
8051 // chain check to trap element accessors being installed on the prototype
8052 // chain, which would cause elements to go to dictionary mode and result
8053 // in a map change.
8054 BuildCheckPrototypeMaps(
8055 handle(JSObject::cast(receiver_map->prototype()), isolate()),
8056 Handle<JSObject>::null());
8057
8058 HValue* search_element = Pop();
8059 HValue* receiver = Pop();
8060 Drop(1); // Drop function.
8061
8062 ArrayIndexOfMode mode = (id == kArrayIndexOf)
8063 ? kFirstIndexOf : kLastIndexOf;
8064 HValue* index = BuildArrayIndexOf(receiver, search_element, kind, mode);
8065
8066 if (!ast_context()->IsEffect()) Push(index);
8067 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
8068 if (!ast_context()->IsEffect()) Drop(1);
8069 ast_context()->ReturnValue(index);
8070 return true;
8071 }
8035 default: 8072 default:
8036 // Not yet supported for inlining. 8073 // Not yet supported for inlining.
8037 break; 8074 break;
8038 } 8075 }
8039 return false; 8076 return false;
8040 } 8077 }
8041 8078
8042 8079
8043 bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr, 8080 bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr,
8044 HValue* receiver) { 8081 HValue* receiver) {
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
8317 8354
8318 HInstruction* call = PreProcessCall(New<HCallNewArray>( 8355 HInstruction* call = PreProcessCall(New<HCallNewArray>(
8319 function, arguments_count + 1, site->GetElementsKind())); 8356 function, arguments_count + 1, site->GetElementsKind()));
8320 if (expression->IsCall()) { 8357 if (expression->IsCall()) {
8321 Drop(1); 8358 Drop(1);
8322 } 8359 }
8323 ast_context()->ReturnInstruction(call, expression->id()); 8360 ast_context()->ReturnInstruction(call, expression->id());
8324 } 8361 }
8325 8362
8326 8363
8364 HValue* HOptimizedGraphBuilder::BuildArrayIndexOf(HValue* receiver,
8365 HValue* search_element,
8366 ElementsKind kind,
8367 ArrayIndexOfMode mode) {
8368 ASSERT(IsFastElementsKind(kind));
8369
8370 NoObservableSideEffectsScope no_effects(this);
8371
8372 HValue* elements = AddLoadElements(receiver);
8373 HValue* length = AddLoadArrayLength(receiver, kind);
8374
8375 HValue* initial;
8376 HValue* terminating;
8377 Token::Value token;
8378 LoopBuilder::Direction direction;
8379 if (mode == kFirstIndexOf) {
8380 initial = graph()->GetConstant0();
8381 terminating = length;
8382 token = Token::LT;
8383 direction = LoopBuilder::kPostIncrement;
8384 } else {
8385 ASSERT_EQ(kLastIndexOf, mode);
8386 initial = length;
8387 terminating = graph()->GetConstant0();
8388 token = Token::GTE;
8389 direction = LoopBuilder::kPreDecrement;
8390 }
8391
8392 Push(graph()->GetConstantMinus1());
8393 if (IsFastDoubleElementsKind(kind) || IsFastSmiElementsKind(kind)) {
8394 LoopBuilder loop(this, context(), direction);
8395 {
8396 HValue* index = loop.BeginBody(initial, terminating, token);
8397 HValue* element = AddUncasted<HLoadKeyed>(
8398 elements, index, static_cast<HValue*>(NULL),
8399 kind, ALLOW_RETURN_HOLE);
8400 IfBuilder if_issame(this);
8401 if (IsFastDoubleElementsKind(kind)) {
8402 if_issame.If<HCompareNumericAndBranch>(
8403 element, search_element, Token::EQ_STRICT);
8404 } else {
8405 if_issame.If<HCompareObjectEqAndBranch>(element, search_element);
8406 }
8407 if_issame.Then();
8408 {
8409 Drop(1);
8410 Push(index);
8411 loop.Break();
8412 }
8413 if_issame.End();
8414 }
8415 loop.EndBody();
8416 } else {
8417 IfBuilder if_isstring(this);
8418 if_isstring.If<HIsStringAndBranch>(search_element);
8419 if_isstring.Then();
8420 {
8421 LoopBuilder loop(this, context(), direction);
8422 {
8423 HValue* index = loop.BeginBody(initial, terminating, token);
8424 HValue* element = AddUncasted<HLoadKeyed>(
8425 elements, index, static_cast<HValue*>(NULL),
8426 kind, ALLOW_RETURN_HOLE);
8427 IfBuilder if_issame(this);
8428 if_issame.If<HIsStringAndBranch>(element);
8429 if_issame.AndIf<HStringCompareAndBranch>(
8430 element, search_element, Token::EQ_STRICT);
8431 if_issame.Then();
8432 {
8433 Drop(1);
8434 Push(index);
8435 loop.Break();
8436 }
8437 if_issame.End();
8438 }
8439 loop.EndBody();
8440 }
8441 if_isstring.Else();
8442 {
8443 IfBuilder if_isheapnumber(this);
8444 if_isheapnumber.IfNot<HIsSmiAndBranch>(search_element);
8445 HCompareMap* isheapnumber = if_isheapnumber.AndIf<HCompareMap>(
8446 search_element, isolate()->factory()->heap_number_map());
8447 if_isheapnumber.Then();
8448 {
8449 HValue* search_number = Add<HLoadNamedField>(
8450 search_element, isheapnumber,
8451 HObjectAccess::ForHeapNumberValue());
8452 LoopBuilder loop(this, context(), direction);
8453 {
8454 HValue* index = loop.BeginBody(initial, terminating, token);
8455 HValue* element = AddUncasted<HLoadKeyed>(
8456 elements, index, static_cast<HValue*>(NULL),
8457 kind, ALLOW_RETURN_HOLE);
8458 IfBuilder if_issame(this);
8459 HCompareMap* issame = if_issame.If<HCompareMap>(
8460 element, isolate()->factory()->heap_number_map());
8461 if_issame.And();
8462 HValue* number = Add<HLoadNamedField>(
8463 element, issame, HObjectAccess::ForHeapNumberValue());
8464 if_issame.If<HCompareNumericAndBranch>(
8465 number, search_number, Token::EQ_STRICT);
8466 if_issame.Then();
8467 {
8468 Drop(1);
8469 Push(index);
8470 loop.Break();
8471 }
8472 if_issame.End();
8473 }
8474 loop.EndBody();
8475 }
8476 if_isheapnumber.Else();
8477 {
8478 LoopBuilder loop(this, context(), direction);
8479 {
8480 HValue* index = loop.BeginBody(initial, terminating, token);
8481 HValue* element = AddUncasted<HLoadKeyed>(
8482 elements, index, static_cast<HValue*>(NULL),
8483 kind, ALLOW_RETURN_HOLE);
8484 IfBuilder if_issame(this);
8485 if_issame.If<HCompareObjectEqAndBranch>(
8486 element, search_element);
8487 if_issame.Then();
8488 {
8489 Drop(1);
8490 Push(index);
8491 loop.Break();
8492 }
8493 if_issame.End();
8494 }
8495 loop.EndBody();
8496 }
8497 if_isheapnumber.End();
8498 }
8499 if_isstring.End();
8500 }
8501
8502 return Pop();
8503 }
8504
8505
8327 bool HOptimizedGraphBuilder::TryHandleArrayCall(Call* expr, HValue* function) { 8506 bool HOptimizedGraphBuilder::TryHandleArrayCall(Call* expr, HValue* function) {
8328 if (!array_function().is_identical_to(expr->target())) { 8507 if (!array_function().is_identical_to(expr->target())) {
8329 return false; 8508 return false;
8330 } 8509 }
8331 8510
8332 Handle<AllocationSite> site = expr->allocation_site(); 8511 Handle<AllocationSite> site = expr->allocation_site();
8333 if (site.is_null()) return false; 8512 if (site.is_null()) return false;
8334 8513
8335 BuildArrayCall(expr, 8514 BuildArrayCall(expr,
8336 expr->arguments()->length(), 8515 expr->arguments()->length(),
(...skipping 3539 matching lines...) Expand 10 before | Expand all | Expand 10 after
11876 if (ShouldProduceTraceOutput()) { 12055 if (ShouldProduceTraceOutput()) {
11877 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 12056 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
11878 } 12057 }
11879 12058
11880 #ifdef DEBUG 12059 #ifdef DEBUG
11881 graph_->Verify(false); // No full verify. 12060 graph_->Verify(false); // No full verify.
11882 #endif 12061 #endif
11883 } 12062 }
11884 12063
11885 } } // namespace v8::internal 12064 } } // namespace v8::internal
OLDNEW
« 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