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 "src/crankshaft/hydrogen.h" | 5 #include "src/crankshaft/hydrogen.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <sstream> | 8 #include <sstream> |
9 | 9 |
10 #include "src/allocation-site-scopes.h" | 10 #include "src/allocation-site-scopes.h" |
(...skipping 7543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7554 if (TryArgumentsAccess(expr)) return; | 7554 if (TryArgumentsAccess(expr)) return; |
7555 | 7555 |
7556 CHECK_ALIVE(VisitForValue(expr->obj())); | 7556 CHECK_ALIVE(VisitForValue(expr->obj())); |
7557 if (!expr->key()->IsPropertyName() || expr->IsStringAccess()) { | 7557 if (!expr->key()->IsPropertyName() || expr->IsStringAccess()) { |
7558 CHECK_ALIVE(VisitForValue(expr->key())); | 7558 CHECK_ALIVE(VisitForValue(expr->key())); |
7559 } | 7559 } |
7560 | 7560 |
7561 BuildLoad(expr, expr->id()); | 7561 BuildLoad(expr, expr->id()); |
7562 } | 7562 } |
7563 | 7563 |
7564 | 7564 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant, |
7565 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant) { | 7565 bool ensure_no_elements) { |
7566 HCheckMaps* check = Add<HCheckMaps>( | 7566 HCheckMaps* check = Add<HCheckMaps>( |
7567 Add<HConstant>(constant), handle(constant->map())); | 7567 Add<HConstant>(constant), handle(constant->map())); |
7568 check->ClearDependsOnFlag(kElementsKind); | 7568 check->ClearDependsOnFlag(kElementsKind); |
| 7569 if (ensure_no_elements) { |
| 7570 // TODO(ishell): remove this once we support NO_ELEMENTS elements kind. |
| 7571 HValue* elements = AddLoadElements(check, nullptr); |
| 7572 HValue* empty_elements = |
| 7573 Add<HConstant>(isolate()->factory()->empty_fixed_array()); |
| 7574 IfBuilder if_empty(this); |
| 7575 if_empty.IfNot<HCompareObjectEqAndBranch>(elements, empty_elements); |
| 7576 if_empty.ThenDeopt(DeoptimizeReason::kWrongMap); |
| 7577 if_empty.End(); |
| 7578 } |
7569 return check; | 7579 return check; |
7570 } | 7580 } |
7571 | 7581 |
7572 | |
7573 HInstruction* HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype, | 7582 HInstruction* HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype, |
7574 Handle<JSObject> holder) { | 7583 Handle<JSObject> holder, |
| 7584 bool ensure_no_elements) { |
7575 PrototypeIterator iter(isolate(), prototype, kStartAtReceiver); | 7585 PrototypeIterator iter(isolate(), prototype, kStartAtReceiver); |
7576 while (holder.is_null() || | 7586 while (holder.is_null() || |
7577 !PrototypeIterator::GetCurrent(iter).is_identical_to(holder)) { | 7587 !PrototypeIterator::GetCurrent(iter).is_identical_to(holder)) { |
7578 BuildConstantMapCheck(PrototypeIterator::GetCurrent<JSObject>(iter)); | 7588 BuildConstantMapCheck(PrototypeIterator::GetCurrent<JSObject>(iter), |
| 7589 ensure_no_elements); |
7579 iter.Advance(); | 7590 iter.Advance(); |
7580 if (iter.IsAtEnd()) { | 7591 if (iter.IsAtEnd()) { |
7581 return NULL; | 7592 return NULL; |
7582 } | 7593 } |
7583 } | 7594 } |
7584 return BuildConstantMapCheck(PrototypeIterator::GetCurrent<JSObject>(iter)); | 7595 return BuildConstantMapCheck(holder); |
7585 } | 7596 } |
7586 | 7597 |
7587 | 7598 |
7588 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, | 7599 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, |
7589 Handle<Map> receiver_map) { | 7600 Handle<Map> receiver_map) { |
7590 if (!holder.is_null()) { | 7601 if (!holder.is_null()) { |
7591 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); | 7602 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); |
7592 BuildCheckPrototypeMaps(prototype, holder); | 7603 BuildCheckPrototypeMaps(prototype, holder); |
7593 } | 7604 } |
7594 } | 7605 } |
(...skipping 840 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8435 HInstruction* result = | 8446 HInstruction* result = |
8436 New<HLoadNamedField>(object, checked_object, access); | 8447 New<HLoadNamedField>(object, checked_object, access); |
8437 ast_context()->ReturnInstruction(result, ast_id); | 8448 ast_context()->ReturnInstruction(result, ast_id); |
8438 return true; | 8449 return true; |
8439 } | 8450 } |
8440 default: | 8451 default: |
8441 return false; | 8452 return false; |
8442 } | 8453 } |
8443 } | 8454 } |
8444 | 8455 |
| 8456 // static |
| 8457 bool HOptimizedGraphBuilder::NoElementsInPrototypeChain( |
| 8458 Handle<Map> receiver_map) { |
| 8459 // TODO(ishell): remove this once we support NO_ELEMENTS elements kind. |
| 8460 PrototypeIterator iter(receiver_map); |
| 8461 Handle<Object> empty_fixed_array = |
| 8462 iter.isolate()->factory()->empty_fixed_array(); |
| 8463 while (true) { |
| 8464 Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter); |
| 8465 if (current->elements() != *empty_fixed_array) return false; |
| 8466 iter.Advance(); |
| 8467 if (iter.IsAtEnd()) { |
| 8468 return true; |
| 8469 } |
| 8470 } |
| 8471 } |
| 8472 |
8445 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( | 8473 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall( |
8446 Handle<JSFunction> function, Handle<Map> receiver_map, BailoutId ast_id, | 8474 Handle<JSFunction> function, Handle<Map> receiver_map, BailoutId ast_id, |
8447 int args_count_no_receiver) { | 8475 int args_count_no_receiver) { |
8448 if (!function->shared()->HasBuiltinFunctionId()) return false; | 8476 if (!function->shared()->HasBuiltinFunctionId()) return false; |
8449 BuiltinFunctionId id = function->shared()->builtin_function_id(); | 8477 BuiltinFunctionId id = function->shared()->builtin_function_id(); |
8450 int argument_count = args_count_no_receiver + 1; // Plus receiver. | 8478 int argument_count = args_count_no_receiver + 1; // Plus receiver. |
8451 | 8479 |
8452 if (receiver_map.is_null()) { | 8480 if (receiver_map.is_null()) { |
8453 HValue* receiver = environment()->ExpressionStackAt(args_count_no_receiver); | 8481 HValue* receiver = environment()->ExpressionStackAt(args_count_no_receiver); |
8454 if (receiver->IsConstant() && | 8482 if (receiver->IsConstant() && |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8689 if (!ast_context()->IsEffect()) Push(new_size); | 8717 if (!ast_context()->IsEffect()) Push(new_size); |
8690 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 8718 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
8691 if (!ast_context()->IsEffect()) Drop(1); | 8719 if (!ast_context()->IsEffect()) Drop(1); |
8692 } | 8720 } |
8693 | 8721 |
8694 ast_context()->ReturnValue(new_size); | 8722 ast_context()->ReturnValue(new_size); |
8695 return true; | 8723 return true; |
8696 } | 8724 } |
8697 case kArrayShift: { | 8725 case kArrayShift: { |
8698 if (!CanInlineArrayResizeOperation(receiver_map)) return false; | 8726 if (!CanInlineArrayResizeOperation(receiver_map)) return false; |
| 8727 if (!NoElementsInPrototypeChain(receiver_map)) return false; |
8699 ElementsKind kind = receiver_map->elements_kind(); | 8728 ElementsKind kind = receiver_map->elements_kind(); |
8700 | 8729 |
8701 // If there may be elements accessors in the prototype chain, the fast | 8730 // If there may be elements accessors in the prototype chain, the fast |
8702 // inlined version can't be used. | 8731 // inlined version can't be used. |
8703 if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false; | 8732 if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false; |
8704 | 8733 |
8705 // If there currently can be no elements accessors on the prototype chain, | 8734 // If there currently can be no elements accessors on the prototype chain, |
8706 // it doesn't mean that there won't be any later. Install a full prototype | 8735 // it doesn't mean that there won't be any later. Install a full prototype |
8707 // chain check to trap element accessors being installed on the prototype | 8736 // chain check to trap element accessors being installed on the prototype |
8708 // chain, which would cause elements to go to dictionary mode and result | 8737 // chain, which would cause elements to go to dictionary mode and result |
8709 // in a map change. | 8738 // in a map change. |
8710 BuildCheckPrototypeMaps( | 8739 BuildCheckPrototypeMaps( |
8711 handle(JSObject::cast(receiver_map->prototype()), isolate()), | 8740 handle(JSObject::cast(receiver_map->prototype()), isolate()), |
8712 Handle<JSObject>::null()); | 8741 Handle<JSObject>::null(), true); |
8713 | 8742 |
8714 // Threshold for fast inlined Array.shift(). | 8743 // Threshold for fast inlined Array.shift(). |
8715 HConstant* inline_threshold = Add<HConstant>(static_cast<int32_t>(16)); | 8744 HConstant* inline_threshold = Add<HConstant>(static_cast<int32_t>(16)); |
8716 | 8745 |
8717 Drop(args_count_no_receiver); | 8746 Drop(args_count_no_receiver); |
8718 HValue* result; | 8747 HValue* result; |
8719 HValue* receiver = Pop(); | 8748 HValue* receiver = Pop(); |
8720 HValue* checked_object = AddCheckMap(receiver, receiver_map); | 8749 HValue* checked_object = AddCheckMap(receiver, receiver_map); |
8721 HValue* length = Add<HLoadNamedField>( | 8750 HValue* length = Add<HLoadNamedField>( |
8722 receiver, checked_object, HObjectAccess::ForArrayLength(kind)); | 8751 receiver, checked_object, HObjectAccess::ForArrayLength(kind)); |
(...skipping 4256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12979 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13008 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
12980 } | 13009 } |
12981 | 13010 |
12982 #ifdef DEBUG | 13011 #ifdef DEBUG |
12983 graph_->Verify(false); // No full verify. | 13012 graph_->Verify(false); // No full verify. |
12984 #endif | 13013 #endif |
12985 } | 13014 } |
12986 | 13015 |
12987 } // namespace internal | 13016 } // namespace internal |
12988 } // namespace v8 | 13017 } // namespace v8 |
OLD | NEW |