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

Side by Side Diff: src/hydrogen.cc

Issue 22339018: Deoptimization is easier to diagnose when there is a text reason. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed comments Created 7 years, 4 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/hydrogen-instructions.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 // 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698