| 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 |