OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |