OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 806 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
817 ASSERT(did_then_); | 817 ASSERT(did_then_); |
818 ASSERT(!captured_); | 818 ASSERT(!captured_); |
819 ASSERT(!finished_); | 819 ASSERT(!finished_); |
820 last_true_block_ = builder_->current_block(); | 820 last_true_block_ = builder_->current_block(); |
821 ASSERT(first_true_block_ == NULL || !last_true_block_->IsFinished()); | 821 ASSERT(first_true_block_ == NULL || !last_true_block_->IsFinished()); |
822 builder_->set_current_block(first_false_block_); | 822 builder_->set_current_block(first_false_block_); |
823 did_else_ = true; | 823 did_else_ = true; |
824 } | 824 } |
825 | 825 |
826 | 826 |
827 void HGraphBuilder::IfBuilder::Deopt() { | 827 void HGraphBuilder::IfBuilder::Deopt(const char* reason) { |
828 ASSERT(did_then_); | 828 ASSERT(did_then_); |
829 if (did_else_) { | 829 if (did_else_) { |
830 deopt_else_ = true; | 830 deopt_else_ = true; |
831 } else { | 831 } else { |
832 deopt_then_ = true; | 832 deopt_then_ = true; |
833 } | 833 } |
834 builder_->Add<HDeoptimize>(Deoptimizer::EAGER); | 834 builder_->Add<HDeoptimize>(reason, Deoptimizer::EAGER); |
835 } | 835 } |
836 | 836 |
837 | 837 |
838 void HGraphBuilder::IfBuilder::Return(HValue* value) { | 838 void HGraphBuilder::IfBuilder::Return(HValue* value) { |
839 HBasicBlock* block = builder_->current_block(); | 839 HBasicBlock* block = builder_->current_block(); |
840 HValue* parameter_count = builder_->graph()->GetConstantMinus1(); | 840 HValue* parameter_count = builder_->graph()->GetConstantMinus1(); |
841 block->FinishExit(builder_->New<HReturn>(value, parameter_count)); | 841 block->FinishExit(builder_->New<HReturn>(value, parameter_count)); |
842 builder_->set_current_block(NULL); | 842 builder_->set_current_block(NULL); |
843 if (did_else_) { | 843 if (did_else_) { |
844 first_false_block_ = NULL; | 844 first_false_block_ = NULL; |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1027 } | 1027 } |
1028 | 1028 |
1029 | 1029 |
1030 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { | 1030 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { |
1031 if (obj->type().IsHeapObject()) return obj; | 1031 if (obj->type().IsHeapObject()) return obj; |
1032 return Add<HCheckHeapObject>(obj); | 1032 return Add<HCheckHeapObject>(obj); |
1033 } | 1033 } |
1034 | 1034 |
1035 | 1035 |
1036 void HGraphBuilder::FinishExitWithHardDeoptimization( | 1036 void HGraphBuilder::FinishExitWithHardDeoptimization( |
1037 HBasicBlock* continuation) { | 1037 const char* reason, HBasicBlock* continuation) { |
1038 PadEnvironmentForContinuation(current_block(), continuation); | 1038 PadEnvironmentForContinuation(current_block(), continuation); |
1039 Add<HDeoptimize>(Deoptimizer::EAGER); | 1039 Add<HDeoptimize>(reason, Deoptimizer::EAGER); |
1040 if (no_side_effects_scope_count_ > 0) { | 1040 if (no_side_effects_scope_count_ > 0) { |
1041 current_block()->GotoNoSimulate(continuation); | 1041 current_block()->GotoNoSimulate(continuation); |
1042 } else { | 1042 } else { |
1043 current_block()->Goto(continuation); | 1043 current_block()->Goto(continuation); |
1044 } | 1044 } |
1045 } | 1045 } |
1046 | 1046 |
1047 | 1047 |
1048 void HGraphBuilder::PadEnvironmentForContinuation( | 1048 void HGraphBuilder::PadEnvironmentForContinuation( |
1049 HBasicBlock* from, | 1049 HBasicBlock* from, |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1101 Token::GTE); | 1101 Token::GTE); |
1102 capacity_checker.Then(); | 1102 capacity_checker.Then(); |
1103 | 1103 |
1104 HValue* context = environment()->context(); | 1104 HValue* context = environment()->context(); |
1105 | 1105 |
1106 HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap)); | 1106 HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap)); |
1107 HValue* max_capacity = Add<HAdd>(current_capacity, max_gap); | 1107 HValue* max_capacity = Add<HAdd>(current_capacity, max_gap); |
1108 IfBuilder key_checker(this); | 1108 IfBuilder key_checker(this); |
1109 key_checker.If<HCompareNumericAndBranch>(key, max_capacity, Token::LT); | 1109 key_checker.If<HCompareNumericAndBranch>(key, max_capacity, Token::LT); |
1110 key_checker.Then(); | 1110 key_checker.Then(); |
1111 key_checker.ElseDeopt(); | 1111 key_checker.ElseDeopt("Key out of capacity range"); |
1112 key_checker.End(); | 1112 key_checker.End(); |
1113 | 1113 |
1114 HValue* new_capacity = BuildNewElementsCapacity(key); | 1114 HValue* new_capacity = BuildNewElementsCapacity(key); |
1115 HValue* new_elements = BuildGrowElementsCapacity(object, elements, | 1115 HValue* new_elements = BuildGrowElementsCapacity(object, elements, |
1116 kind, kind, length, | 1116 kind, kind, length, |
1117 new_capacity); | 1117 new_capacity); |
1118 | 1118 |
1119 environment()->Push(new_elements); | 1119 environment()->Push(new_elements); |
1120 capacity_checker.Else(); | 1120 capacity_checker.Else(); |
1121 | 1121 |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1257 Add<HLoadExternalArrayPointer>(elements); | 1257 Add<HLoadExternalArrayPointer>(elements); |
1258 IfBuilder length_checker(this); | 1258 IfBuilder length_checker(this); |
1259 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); | 1259 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); |
1260 length_checker.Then(); | 1260 length_checker.Then(); |
1261 IfBuilder negative_checker(this); | 1261 IfBuilder negative_checker(this); |
1262 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( | 1262 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( |
1263 key, graph()->GetConstant0(), Token::GTE); | 1263 key, graph()->GetConstant0(), Token::GTE); |
1264 negative_checker.Then(); | 1264 negative_checker.Then(); |
1265 HInstruction* result = AddExternalArrayElementAccess( | 1265 HInstruction* result = AddExternalArrayElementAccess( |
1266 external_elements, key, val, bounds_check, elements_kind, is_store); | 1266 external_elements, key, val, bounds_check, elements_kind, is_store); |
1267 negative_checker.ElseDeopt(); | 1267 negative_checker.ElseDeopt("Negative key encountered"); |
1268 length_checker.End(); | 1268 length_checker.End(); |
1269 return result; | 1269 return result; |
1270 } else { | 1270 } else { |
1271 ASSERT(store_mode == STANDARD_STORE); | 1271 ASSERT(store_mode == STANDARD_STORE); |
1272 checked_key = Add<HBoundsCheck>(key, length); | 1272 checked_key = Add<HBoundsCheck>(key, length); |
1273 HLoadExternalArrayPointer* external_elements = | 1273 HLoadExternalArrayPointer* external_elements = |
1274 Add<HLoadExternalArrayPointer>(elements); | 1274 Add<HLoadExternalArrayPointer>(elements); |
1275 return AddExternalArrayElementAccess( | 1275 return AddExternalArrayElementAccess( |
1276 external_elements, checked_key, val, | 1276 external_elements, checked_key, val, |
1277 mapcheck, elements_kind, is_store); | 1277 mapcheck, elements_kind, is_store); |
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1744 if_nil.Then(); | 1744 if_nil.Then(); |
1745 if_nil.Else(); | 1745 if_nil.Else(); |
1746 if (type->NumClasses() == 1) { | 1746 if (type->NumClasses() == 1) { |
1747 BuildCheckHeapObject(value); | 1747 BuildCheckHeapObject(value); |
1748 // For ICs, the map checked below is a sentinel map that gets replaced by | 1748 // For ICs, the map checked below is a sentinel map that gets replaced by |
1749 // the monomorphic map when the code is used as a template to generate a | 1749 // the monomorphic map when the code is used as a template to generate a |
1750 // new IC. For optimized functions, there is no sentinel map, the map | 1750 // new IC. For optimized functions, there is no sentinel map, the map |
1751 // emitted below is the actual monomorphic map. | 1751 // emitted below is the actual monomorphic map. |
1752 BuildCheckMap(value, type->Classes().Current()); | 1752 BuildCheckMap(value, type->Classes().Current()); |
1753 } else { | 1753 } else { |
1754 if_nil.Deopt(); | 1754 if_nil.Deopt("Too many undetectable types"); |
1755 } | 1755 } |
1756 } | 1756 } |
1757 | 1757 |
1758 if_nil.CaptureContinuation(continuation); | 1758 if_nil.CaptureContinuation(continuation); |
1759 } | 1759 } |
1760 | 1760 |
1761 | 1761 |
1762 HValue* HGraphBuilder::BuildCreateAllocationMemento(HValue* previous_object, | 1762 HValue* HGraphBuilder::BuildCreateAllocationMemento(HValue* previous_object, |
1763 int previous_object_size, | 1763 int previous_object_size, |
1764 HValue* alloc_site) { | 1764 HValue* alloc_site) { |
(...skipping 1575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3340 CHECK_ALIVE(VisitForValue(clause->label())); | 3340 CHECK_ALIVE(VisitForValue(clause->label())); |
3341 HValue* label_value = Pop(); | 3341 HValue* label_value = Pop(); |
3342 | 3342 |
3343 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); | 3343 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); |
3344 HBasicBlock* body_block = graph()->CreateBasicBlock(); | 3344 HBasicBlock* body_block = graph()->CreateBasicBlock(); |
3345 | 3345 |
3346 HControlInstruction* compare; | 3346 HControlInstruction* compare; |
3347 | 3347 |
3348 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { | 3348 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { |
3349 if (!clause->compare_type()->Is(Type::Smi())) { | 3349 if (!clause->compare_type()->Is(Type::Smi())) { |
3350 Add<HDeoptimize>(Deoptimizer::SOFT); | 3350 Add<HDeoptimize>("Non-smi switch type", Deoptimizer::SOFT); |
3351 } | 3351 } |
3352 | 3352 |
3353 HCompareNumericAndBranch* compare_ = | 3353 HCompareNumericAndBranch* compare_ = |
3354 new(zone()) HCompareNumericAndBranch(tag_value, | 3354 new(zone()) HCompareNumericAndBranch(tag_value, |
3355 label_value, | 3355 label_value, |
3356 Token::EQ_STRICT); | 3356 Token::EQ_STRICT); |
3357 compare_->set_observed_input_representation( | 3357 compare_->set_observed_input_representation( |
3358 Representation::Smi(), Representation::Smi()); | 3358 Representation::Smi(), Representation::Smi()); |
3359 compare = compare_; | 3359 compare = compare_; |
3360 } else { | 3360 } else { |
(...skipping 1368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4729 current_block()->Goto(join); | 4729 current_block()->Goto(join); |
4730 | 4730 |
4731 set_current_block(if_false); | 4731 set_current_block(if_false); |
4732 } | 4732 } |
4733 } | 4733 } |
4734 | 4734 |
4735 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 4735 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
4736 // know about and do not want to handle ones we've never seen. Otherwise | 4736 // know about and do not want to handle ones we've never seen. Otherwise |
4737 // use a generic IC. | 4737 // use a generic IC. |
4738 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | 4738 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { |
4739 FinishExitWithHardDeoptimization(join); | 4739 FinishExitWithHardDeoptimization("All known maps handled", join); |
4740 } else { | 4740 } else { |
4741 HInstruction* instr = BuildStoreNamedGeneric(object, name, store_value); | 4741 HInstruction* instr = BuildStoreNamedGeneric(object, name, store_value); |
4742 instr->set_position(position); | 4742 instr->set_position(position); |
4743 AddInstruction(instr); | 4743 AddInstruction(instr); |
4744 | 4744 |
4745 if (join != NULL) { | 4745 if (join != NULL) { |
4746 if (!ast_context()->IsEffect()) { | 4746 if (!ast_context()->IsEffect()) { |
4747 Push(result_value); | 4747 Push(result_value); |
4748 } | 4748 } |
4749 current_block()->Goto(join); | 4749 current_block()->Goto(join); |
(...skipping 27 matching lines...) Expand all Loading... |
4777 Property* prop = expr->target()->AsProperty(); | 4777 Property* prop = expr->target()->AsProperty(); |
4778 ASSERT(prop != NULL); | 4778 ASSERT(prop != NULL); |
4779 CHECK_ALIVE(VisitForValue(prop->obj())); | 4779 CHECK_ALIVE(VisitForValue(prop->obj())); |
4780 | 4780 |
4781 if (prop->key()->IsPropertyName()) { | 4781 if (prop->key()->IsPropertyName()) { |
4782 // Named store. | 4782 // Named store. |
4783 CHECK_ALIVE(VisitForValue(expr->value())); | 4783 CHECK_ALIVE(VisitForValue(expr->value())); |
4784 HValue* value = environment()->ExpressionStackAt(0); | 4784 HValue* value = environment()->ExpressionStackAt(0); |
4785 HValue* object = environment()->ExpressionStackAt(1); | 4785 HValue* object = environment()->ExpressionStackAt(1); |
4786 | 4786 |
4787 if (expr->IsUninitialized()) Add<HDeoptimize>(Deoptimizer::SOFT); | 4787 if (expr->IsUninitialized()) { |
| 4788 Add<HDeoptimize>("Insufficient type feedback for property assignment", |
| 4789 Deoptimizer::SOFT); |
| 4790 } |
4788 return BuildStoreNamed(expr, expr->id(), expr->position(), | 4791 return BuildStoreNamed(expr, expr->id(), expr->position(), |
4789 expr->AssignmentId(), prop, object, value, value); | 4792 expr->AssignmentId(), prop, object, value, value); |
4790 } else { | 4793 } else { |
4791 // Keyed store. | 4794 // Keyed store. |
4792 CHECK_ALIVE(VisitForValue(prop->key())); | 4795 CHECK_ALIVE(VisitForValue(prop->key())); |
4793 CHECK_ALIVE(VisitForValue(expr->value())); | 4796 CHECK_ALIVE(VisitForValue(expr->value())); |
4794 HValue* value = environment()->ExpressionStackAt(0); | 4797 HValue* value = environment()->ExpressionStackAt(0); |
4795 HValue* key = environment()->ExpressionStackAt(1); | 4798 HValue* key = environment()->ExpressionStackAt(1); |
4796 HValue* object = environment()->ExpressionStackAt(2); | 4799 HValue* object = environment()->ExpressionStackAt(2); |
4797 bool has_side_effects = false; | 4800 bool has_side_effects = false; |
(...skipping 25 matching lines...) Expand all Loading... |
4823 if (cell->type()->IsConstant()) { | 4826 if (cell->type()->IsConstant()) { |
4824 IfBuilder builder(this); | 4827 IfBuilder builder(this); |
4825 HValue* constant = Add<HConstant>(cell->type()->AsConstant()); | 4828 HValue* constant = Add<HConstant>(cell->type()->AsConstant()); |
4826 if (cell->type()->AsConstant()->IsNumber()) { | 4829 if (cell->type()->AsConstant()->IsNumber()) { |
4827 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ); | 4830 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ); |
4828 } else { | 4831 } else { |
4829 builder.If<HCompareObjectEqAndBranch>(value, constant); | 4832 builder.If<HCompareObjectEqAndBranch>(value, constant); |
4830 } | 4833 } |
4831 builder.Then(); | 4834 builder.Then(); |
4832 builder.Else(); | 4835 builder.Else(); |
4833 Add<HDeoptimize>(Deoptimizer::EAGER); | 4836 Add<HDeoptimize>("Constant global variable assignment", |
| 4837 Deoptimizer::EAGER); |
4834 builder.End(); | 4838 builder.End(); |
4835 } | 4839 } |
4836 HInstruction* instr = | 4840 HInstruction* instr = |
4837 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); | 4841 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); |
4838 instr->set_position(position); | 4842 instr->set_position(position); |
4839 if (instr->HasObservableSideEffects()) { | 4843 if (instr->HasObservableSideEffects()) { |
4840 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 4844 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
4841 } | 4845 } |
4842 } else { | 4846 } else { |
4843 HGlobalObject* global_object = Add<HGlobalObject>(); | 4847 HGlobalObject* global_object = Add<HGlobalObject>(); |
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5264 return BuildLoadNamedField( | 5268 return BuildLoadNamedField( |
5265 object, HObjectAccess::ForStringLength(), typecheck); | 5269 object, HObjectAccess::ForStringLength(), typecheck); |
5266 } | 5270 } |
5267 | 5271 |
5268 | 5272 |
5269 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( | 5273 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( |
5270 HValue* object, | 5274 HValue* object, |
5271 Handle<String> name, | 5275 Handle<String> name, |
5272 Property* expr) { | 5276 Property* expr) { |
5273 if (expr->IsUninitialized()) { | 5277 if (expr->IsUninitialized()) { |
5274 Add<HDeoptimize>(Deoptimizer::SOFT); | 5278 Add<HDeoptimize>("Insufficient feedback for generic named load", |
| 5279 Deoptimizer::SOFT); |
5275 } | 5280 } |
5276 HValue* context = environment()->context(); | 5281 HValue* context = environment()->context(); |
5277 return new(zone()) HLoadNamedGeneric(context, object, name); | 5282 return new(zone()) HLoadNamedGeneric(context, object, name); |
5278 } | 5283 } |
5279 | 5284 |
5280 | 5285 |
5281 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( | 5286 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( |
5282 HValue* object, | 5287 HValue* object, |
5283 Handle<Map> map, | 5288 Handle<Map> map, |
5284 Handle<JSFunction> getter, | 5289 Handle<JSFunction> getter, |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5581 if (position != RelocInfo::kNoPosition) access->set_position(position); | 5586 if (position != RelocInfo::kNoPosition) access->set_position(position); |
5582 if (!is_store) { | 5587 if (!is_store) { |
5583 Push(access); | 5588 Push(access); |
5584 } | 5589 } |
5585 current_block()->GotoNoSimulate(join); | 5590 current_block()->GotoNoSimulate(join); |
5586 set_current_block(other_map); | 5591 set_current_block(other_map); |
5587 } | 5592 } |
5588 | 5593 |
5589 // Deopt if none of the cases matched. | 5594 // Deopt if none of the cases matched. |
5590 NoObservableSideEffectsScope scope(this); | 5595 NoObservableSideEffectsScope scope(this); |
5591 FinishExitWithHardDeoptimization(join); | 5596 FinishExitWithHardDeoptimization("Unknown type in polymorphic element access", |
| 5597 join); |
5592 set_current_block(join); | 5598 set_current_block(join); |
5593 return is_store ? NULL : Pop(); | 5599 return is_store ? NULL : Pop(); |
5594 } | 5600 } |
5595 | 5601 |
5596 | 5602 |
5597 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( | 5603 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( |
5598 HValue* obj, | 5604 HValue* obj, |
5599 HValue* key, | 5605 HValue* key, |
5600 HValue* val, | 5606 HValue* val, |
5601 Expression* expr, | 5607 Expression* expr, |
(...skipping 15 matching lines...) Expand all Loading... |
5617 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); | 5623 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); |
5618 } | 5624 } |
5619 } else if (expr->GetReceiverTypes() != NULL && | 5625 } else if (expr->GetReceiverTypes() != NULL && |
5620 !expr->GetReceiverTypes()->is_empty()) { | 5626 !expr->GetReceiverTypes()->is_empty()) { |
5621 return HandlePolymorphicElementAccess( | 5627 return HandlePolymorphicElementAccess( |
5622 obj, key, val, expr, ast_id, position, is_store, | 5628 obj, key, val, expr, ast_id, position, is_store, |
5623 expr->GetStoreMode(), has_side_effects); | 5629 expr->GetStoreMode(), has_side_effects); |
5624 } else { | 5630 } else { |
5625 if (is_store) { | 5631 if (is_store) { |
5626 if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) { | 5632 if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) { |
5627 Add<HDeoptimize>(Deoptimizer::SOFT); | 5633 Add<HDeoptimize>("Insufficient feedback for keyed store", |
| 5634 Deoptimizer::SOFT); |
5628 } | 5635 } |
5629 instr = BuildStoreKeyedGeneric(obj, key, val); | 5636 instr = BuildStoreKeyedGeneric(obj, key, val); |
5630 } else { | 5637 } else { |
5631 if (expr->AsProperty()->IsUninitialized()) { | 5638 if (expr->AsProperty()->IsUninitialized()) { |
5632 Add<HDeoptimize>(Deoptimizer::SOFT); | 5639 Add<HDeoptimize>("Insufficient feedback for keyed load", |
| 5640 Deoptimizer::SOFT); |
5633 } | 5641 } |
5634 instr = BuildLoadKeyedGeneric(obj, key); | 5642 instr = BuildLoadKeyedGeneric(obj, key); |
5635 } | 5643 } |
5636 AddInstruction(instr); | 5644 AddInstruction(instr); |
5637 } | 5645 } |
5638 if (position != RelocInfo::kNoPosition) instr->set_position(position); | 5646 if (position != RelocInfo::kNoPosition) instr->set_position(position); |
5639 *has_side_effects = instr->HasObservableSideEffects(); | 5647 *has_side_effects = instr->HasObservableSideEffects(); |
5640 return instr; | 5648 return instr; |
5641 } | 5649 } |
5642 | 5650 |
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6069 } | 6077 } |
6070 | 6078 |
6071 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 6079 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
6072 // know about and do not want to handle ones we've never seen. Otherwise | 6080 // know about and do not want to handle ones we've never seen. Otherwise |
6073 // use a generic IC. | 6081 // use a generic IC. |
6074 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { | 6082 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { |
6075 // Because the deopt may be the only path in the polymorphic call, make sure | 6083 // Because the deopt may be the only path in the polymorphic call, make sure |
6076 // that the environment stack matches the depth on deopt that it otherwise | 6084 // that the environment stack matches the depth on deopt that it otherwise |
6077 // would have had after a successful call. | 6085 // would have had after a successful call. |
6078 Drop(argument_count - (ast_context()->IsEffect() ? 0 : 1)); | 6086 Drop(argument_count - (ast_context()->IsEffect() ? 0 : 1)); |
6079 FinishExitWithHardDeoptimization(join); | 6087 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join); |
6080 } else { | 6088 } else { |
6081 HValue* context = environment()->context(); | 6089 HValue* context = environment()->context(); |
6082 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); | 6090 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); |
6083 call->set_position(expr->position()); | 6091 call->set_position(expr->position()); |
6084 PreProcessCall(call); | 6092 PreProcessCall(call); |
6085 | 6093 |
6086 if (join != NULL) { | 6094 if (join != NULL) { |
6087 AddInstruction(call); | 6095 AddInstruction(call); |
6088 if (!ast_context()->IsEffect()) Push(call); | 6096 if (!ast_context()->IsEffect()) Push(call); |
6089 current_block()->Goto(join); | 6097 current_block()->Goto(join); |
(...skipping 1539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7629 | 7637 |
7630 if (expr->op() != Token::ADD || | 7638 if (expr->op() != Token::ADD || |
7631 (left->type().IsNonString() && right->type().IsNonString())) { | 7639 (left->type().IsNonString() && right->type().IsNonString())) { |
7632 // For addition we can only truncate the arguments to number if we can | 7640 // For addition we can only truncate the arguments to number if we can |
7633 // prove that we will not end up in string concatenation mode. | 7641 // prove that we will not end up in string concatenation mode. |
7634 left = TruncateToNumber(left, &left_type); | 7642 left = TruncateToNumber(left, &left_type); |
7635 right = TruncateToNumber(right, &right_type); | 7643 right = TruncateToNumber(right, &right_type); |
7636 } | 7644 } |
7637 | 7645 |
7638 if (left_type->Is(Type::None())) { | 7646 if (left_type->Is(Type::None())) { |
7639 Add<HDeoptimize>(Deoptimizer::SOFT); | 7647 Add<HDeoptimize>("Insufficient type feedback for left side", |
| 7648 Deoptimizer::SOFT); |
7640 // TODO(rossberg): we should be able to get rid of non-continuous defaults. | 7649 // TODO(rossberg): we should be able to get rid of non-continuous defaults. |
7641 left_type = handle(Type::Any(), isolate()); | 7650 left_type = handle(Type::Any(), isolate()); |
7642 } | 7651 } |
7643 if (right_type->Is(Type::None())) { | 7652 if (right_type->Is(Type::None())) { |
7644 Add<HDeoptimize>(Deoptimizer::SOFT); | 7653 Add<HDeoptimize>("Insufficient type feedback for right side", |
| 7654 Deoptimizer::SOFT); |
7645 right_type = handle(Type::Any(), isolate()); | 7655 right_type = handle(Type::Any(), isolate()); |
7646 } | 7656 } |
7647 HInstruction* instr = NULL; | 7657 HInstruction* instr = NULL; |
7648 switch (expr->op()) { | 7658 switch (expr->op()) { |
7649 case Token::ADD: | 7659 case Token::ADD: |
7650 if (left_type->Is(Type::String()) && right_type->Is(Type::String())) { | 7660 if (left_type->Is(Type::String()) && right_type->Is(Type::String())) { |
7651 BuildCheckHeapObject(left); | 7661 BuildCheckHeapObject(left); |
7652 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); | 7662 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); |
7653 BuildCheckHeapObject(right); | 7663 BuildCheckHeapObject(right); |
7654 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); | 7664 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7984 // TODO(olivf) InvokeFunction produces a check for the parameter count, | 7994 // TODO(olivf) InvokeFunction produces a check for the parameter count, |
7985 // even though we are certain to pass the correct number of arguments here. | 7995 // even though we are certain to pass the correct number of arguments here. |
7986 HInstruction* result = new(zone()) HInvokeFunction(context, function, 2); | 7996 HInstruction* result = new(zone()) HInvokeFunction(context, function, 2); |
7987 result->set_position(expr->position()); | 7997 result->set_position(expr->position()); |
7988 return ast_context()->ReturnInstruction(result, expr->id()); | 7998 return ast_context()->ReturnInstruction(result, expr->id()); |
7989 } | 7999 } |
7990 | 8000 |
7991 // Cases handled below depend on collected type feedback. They should | 8001 // Cases handled below depend on collected type feedback. They should |
7992 // soft deoptimize when there is no type feedback. | 8002 // soft deoptimize when there is no type feedback. |
7993 if (combined_type->Is(Type::None())) { | 8003 if (combined_type->Is(Type::None())) { |
7994 Add<HDeoptimize>(Deoptimizer::SOFT); | 8004 Add<HDeoptimize>("insufficient type feedback for combined type", |
| 8005 Deoptimizer::SOFT); |
7995 combined_type = left_type = right_type = handle(Type::Any(), isolate()); | 8006 combined_type = left_type = right_type = handle(Type::Any(), isolate()); |
7996 } | 8007 } |
7997 | 8008 |
7998 if (combined_type->Is(Type::Receiver())) { | 8009 if (combined_type->Is(Type::Receiver())) { |
7999 switch (op) { | 8010 switch (op) { |
8000 case Token::EQ: | 8011 case Token::EQ: |
8001 case Token::EQ_STRICT: { | 8012 case Token::EQ_STRICT: { |
8002 // Can we get away with map check and not instance type check? | 8013 // Can we get away with map check and not instance type check? |
8003 if (combined_type->IsClass()) { | 8014 if (combined_type->IsClass()) { |
8004 Handle<Map> map = combined_type->AsClass(); | 8015 Handle<Map> map = combined_type->AsClass(); |
(...skipping 1702 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9707 if (ShouldProduceTraceOutput()) { | 9718 if (ShouldProduceTraceOutput()) { |
9708 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9719 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
9709 } | 9720 } |
9710 | 9721 |
9711 #ifdef DEBUG | 9722 #ifdef DEBUG |
9712 graph_->Verify(false); // No full verify. | 9723 graph_->Verify(false); // No full verify. |
9713 #endif | 9724 #endif |
9714 } | 9725 } |
9715 | 9726 |
9716 } } // namespace v8::internal | 9727 } } // namespace v8::internal |
OLD | NEW |