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/hydrogen.h" | 5 #include "src/hydrogen.h" |
6 | 6 |
7 #include <sstream> | 7 #include <sstream> |
8 | 8 |
9 #include "src/v8.h" | 9 #include "src/v8.h" |
10 | 10 |
(...skipping 913 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
924 DCHECK(did_then_); | 924 DCHECK(did_then_); |
925 DCHECK(!captured_); | 925 DCHECK(!captured_); |
926 DCHECK(!finished_); | 926 DCHECK(!finished_); |
927 AddMergeAtJoinBlock(false); | 927 AddMergeAtJoinBlock(false); |
928 builder()->set_current_block(first_false_block_); | 928 builder()->set_current_block(first_false_block_); |
929 pending_merge_block_ = true; | 929 pending_merge_block_ = true; |
930 did_else_ = true; | 930 did_else_ = true; |
931 } | 931 } |
932 | 932 |
933 | 933 |
934 void HGraphBuilder::IfBuilder::Deopt(const char* reason) { | 934 void HGraphBuilder::IfBuilder::Deopt(Deoptimizer::DeoptReason reason) { |
935 DCHECK(did_then_); | 935 DCHECK(did_then_); |
936 builder()->Add<HDeoptimize>(reason, Deoptimizer::EAGER); | 936 builder()->Add<HDeoptimize>(reason, Deoptimizer::EAGER); |
937 AddMergeAtJoinBlock(true); | 937 AddMergeAtJoinBlock(true); |
938 } | 938 } |
939 | 939 |
940 | 940 |
941 void HGraphBuilder::IfBuilder::Return(HValue* value) { | 941 void HGraphBuilder::IfBuilder::Return(HValue* value) { |
942 HValue* parameter_count = builder()->graph()->GetConstantMinus1(); | 942 HValue* parameter_count = builder()->graph()->GetConstantMinus1(); |
943 builder()->FinishExitCurrentBlock( | 943 builder()->FinishExitCurrentBlock( |
944 builder()->New<HReturn>(value, parameter_count)); | 944 builder()->New<HReturn>(value, parameter_count)); |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1266 return BuildDecodeField<Map::ElementsKindBits>(bit_field2); | 1266 return BuildDecodeField<Map::ElementsKindBits>(bit_field2); |
1267 } | 1267 } |
1268 | 1268 |
1269 | 1269 |
1270 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { | 1270 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { |
1271 if (obj->type().IsHeapObject()) return obj; | 1271 if (obj->type().IsHeapObject()) return obj; |
1272 return Add<HCheckHeapObject>(obj); | 1272 return Add<HCheckHeapObject>(obj); |
1273 } | 1273 } |
1274 | 1274 |
1275 | 1275 |
1276 void HGraphBuilder::FinishExitWithHardDeoptimization(const char* reason) { | 1276 void HGraphBuilder::FinishExitWithHardDeoptimization( |
| 1277 Deoptimizer::DeoptReason reason) { |
1277 Add<HDeoptimize>(reason, Deoptimizer::EAGER); | 1278 Add<HDeoptimize>(reason, Deoptimizer::EAGER); |
1278 FinishExitCurrentBlock(New<HAbnormalExit>()); | 1279 FinishExitCurrentBlock(New<HAbnormalExit>()); |
1279 } | 1280 } |
1280 | 1281 |
1281 | 1282 |
1282 HValue* HGraphBuilder::BuildCheckString(HValue* string) { | 1283 HValue* HGraphBuilder::BuildCheckString(HValue* string) { |
1283 if (!string->type().IsString()) { | 1284 if (!string->type().IsString()) { |
1284 DCHECK(!string->IsConstant() || | 1285 DCHECK(!string->IsConstant() || |
1285 !HConstant::cast(string)->HasStringValue()); | 1286 !HConstant::cast(string)->HasStringValue()); |
1286 BuildCheckHeapObject(string); | 1287 BuildCheckHeapObject(string); |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1582 HValue* max_global_type = Add<HConstant>(JS_BUILTINS_OBJECT_TYPE); | 1583 HValue* max_global_type = Add<HConstant>(JS_BUILTINS_OBJECT_TYPE); |
1583 | 1584 |
1584 IfBuilder if_global_object(this); | 1585 IfBuilder if_global_object(this); |
1585 if_global_object.If<HCompareNumericAndBranch>(instance_type, | 1586 if_global_object.If<HCompareNumericAndBranch>(instance_type, |
1586 max_global_type, | 1587 max_global_type, |
1587 Token::LTE); | 1588 Token::LTE); |
1588 if_global_object.And(); | 1589 if_global_object.And(); |
1589 if_global_object.If<HCompareNumericAndBranch>(instance_type, | 1590 if_global_object.If<HCompareNumericAndBranch>(instance_type, |
1590 min_global_type, | 1591 min_global_type, |
1591 Token::GTE); | 1592 Token::GTE); |
1592 if_global_object.ThenDeopt("receiver was a global object"); | 1593 if_global_object.ThenDeopt(Deoptimizer::kReceiverWasAGlobalObject); |
1593 if_global_object.End(); | 1594 if_global_object.End(); |
1594 } | 1595 } |
1595 | 1596 |
1596 | 1597 |
1597 void HGraphBuilder::BuildTestForDictionaryProperties( | 1598 void HGraphBuilder::BuildTestForDictionaryProperties( |
1598 HValue* object, | 1599 HValue* object, |
1599 HIfContinuation* continuation) { | 1600 HIfContinuation* continuation) { |
1600 HValue* properties = Add<HLoadNamedField>( | 1601 HValue* properties = Add<HLoadNamedField>( |
1601 object, nullptr, HObjectAccess::ForPropertiesPointer()); | 1602 object, nullptr, HObjectAccess::ForPropertiesPointer()); |
1602 HValue* properties_map = | 1603 HValue* properties_map = |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1912 if_objectiskey.Then(); | 1913 if_objectiskey.Then(); |
1913 { | 1914 { |
1914 // Make the key_index available. | 1915 // Make the key_index available. |
1915 Push(key_index); | 1916 Push(key_index); |
1916 } | 1917 } |
1917 if_objectiskey.JoinContinuation(&found); | 1918 if_objectiskey.JoinContinuation(&found); |
1918 } | 1919 } |
1919 if_objectissmi.Else(); | 1920 if_objectissmi.Else(); |
1920 { | 1921 { |
1921 if (type->Is(Type::SignedSmall())) { | 1922 if (type->Is(Type::SignedSmall())) { |
1922 if_objectissmi.Deopt("Expected smi"); | 1923 if_objectissmi.Deopt(Deoptimizer::kExpectedSmi); |
1923 } else { | 1924 } else { |
1924 // Check if the object is a heap number. | 1925 // Check if the object is a heap number. |
1925 IfBuilder if_objectisnumber(this); | 1926 IfBuilder if_objectisnumber(this); |
1926 HValue* objectisnumber = if_objectisnumber.If<HCompareMap>( | 1927 HValue* objectisnumber = if_objectisnumber.If<HCompareMap>( |
1927 object, isolate()->factory()->heap_number_map()); | 1928 object, isolate()->factory()->heap_number_map()); |
1928 if_objectisnumber.Then(); | 1929 if_objectisnumber.Then(); |
1929 { | 1930 { |
1930 // Compute hash for heap number similar to double_get_hash(). | 1931 // Compute hash for heap number similar to double_get_hash(). |
1931 HValue* low = Add<HLoadNamedField>( | 1932 HValue* low = Add<HLoadNamedField>( |
1932 object, objectisnumber, | 1933 object, objectisnumber, |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1967 } | 1968 } |
1968 if_keyeqobject.JoinContinuation(&found); | 1969 if_keyeqobject.JoinContinuation(&found); |
1969 } | 1970 } |
1970 if_keyisheapnumber.JoinContinuation(&found); | 1971 if_keyisheapnumber.JoinContinuation(&found); |
1971 } | 1972 } |
1972 if_keyisnotsmi.JoinContinuation(&found); | 1973 if_keyisnotsmi.JoinContinuation(&found); |
1973 } | 1974 } |
1974 if_objectisnumber.Else(); | 1975 if_objectisnumber.Else(); |
1975 { | 1976 { |
1976 if (type->Is(Type::Number())) { | 1977 if (type->Is(Type::Number())) { |
1977 if_objectisnumber.Deopt("Expected heap number"); | 1978 if_objectisnumber.Deopt(Deoptimizer::kExpectedHeapNumber); |
1978 } | 1979 } |
1979 } | 1980 } |
1980 if_objectisnumber.JoinContinuation(&found); | 1981 if_objectisnumber.JoinContinuation(&found); |
1981 } | 1982 } |
1982 } | 1983 } |
1983 if_objectissmi.JoinContinuation(&found); | 1984 if_objectissmi.JoinContinuation(&found); |
1984 | 1985 |
1985 // Check for cache hit. | 1986 // Check for cache hit. |
1986 IfBuilder if_found(this, &found); | 1987 IfBuilder if_found(this, &found); |
1987 if_found.Then(); | 1988 if_found.Then(); |
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2440 NoObservableSideEffectsScope no_effects(this); | 2441 NoObservableSideEffectsScope no_effects(this); |
2441 IfBuilder length_checker(this); | 2442 IfBuilder length_checker(this); |
2442 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); | 2443 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); |
2443 length_checker.Then(); | 2444 length_checker.Then(); |
2444 IfBuilder negative_checker(this); | 2445 IfBuilder negative_checker(this); |
2445 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( | 2446 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( |
2446 key, graph()->GetConstant0(), Token::GTE); | 2447 key, graph()->GetConstant0(), Token::GTE); |
2447 negative_checker.Then(); | 2448 negative_checker.Then(); |
2448 HInstruction* result = AddElementAccess( | 2449 HInstruction* result = AddElementAccess( |
2449 backing_store, key, val, bounds_check, elements_kind, access_type); | 2450 backing_store, key, val, bounds_check, elements_kind, access_type); |
2450 negative_checker.ElseDeopt("Negative key encountered"); | 2451 negative_checker.ElseDeopt(Deoptimizer::kNegativeKeyEncountered); |
2451 negative_checker.End(); | 2452 negative_checker.End(); |
2452 length_checker.End(); | 2453 length_checker.End(); |
2453 return result; | 2454 return result; |
2454 } else { | 2455 } else { |
2455 DCHECK(store_mode == STANDARD_STORE); | 2456 DCHECK(store_mode == STANDARD_STORE); |
2456 checked_key = Add<HBoundsCheck>(key, length); | 2457 checked_key = Add<HBoundsCheck>(key, length); |
2457 return AddElementAccess( | 2458 return AddElementAccess( |
2458 backing_store, checked_key, val, | 2459 backing_store, checked_key, val, |
2459 checked_object, elements_kind, access_type); | 2460 checked_object, elements_kind, access_type); |
2460 } | 2461 } |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2525 Token::EQ); | 2526 Token::EQ); |
2526 if_builder.Then(); | 2527 if_builder.Then(); |
2527 const int initial_capacity = JSArray::kPreallocatedArrayElements; | 2528 const int initial_capacity = JSArray::kPreallocatedArrayElements; |
2528 HConstant* initial_capacity_node = Add<HConstant>(initial_capacity); | 2529 HConstant* initial_capacity_node = Add<HConstant>(initial_capacity); |
2529 Push(initial_capacity_node); // capacity | 2530 Push(initial_capacity_node); // capacity |
2530 Push(constant_zero); // length | 2531 Push(constant_zero); // length |
2531 if_builder.Else(); | 2532 if_builder.Else(); |
2532 if (!(top_info()->IsStub()) && | 2533 if (!(top_info()->IsStub()) && |
2533 IsFastPackedElementsKind(array_builder->kind())) { | 2534 IsFastPackedElementsKind(array_builder->kind())) { |
2534 // We'll come back later with better (holey) feedback. | 2535 // We'll come back later with better (holey) feedback. |
2535 if_builder.Deopt("Holey array despite packed elements_kind feedback"); | 2536 if_builder.Deopt( |
| 2537 Deoptimizer::kHoleyArrayDespitePackedElements_kindFeedback); |
2536 } else { | 2538 } else { |
2537 Push(checked_length); // capacity | 2539 Push(checked_length); // capacity |
2538 Push(checked_length); // length | 2540 Push(checked_length); // length |
2539 } | 2541 } |
2540 if_builder.End(); | 2542 if_builder.End(); |
2541 | 2543 |
2542 // Figure out total size | 2544 // Figure out total size |
2543 HValue* length = Pop(); | 2545 HValue* length = Pop(); |
2544 HValue* capacity = Pop(); | 2546 HValue* capacity = Pop(); |
2545 return array_builder->AllocateArray(capacity, max_alloc_length, length); | 2547 return array_builder->AllocateArray(capacity, max_alloc_length, length); |
(...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3064 // emitted below is the actual monomorphic map. | 3066 // emitted below is the actual monomorphic map. |
3065 if (map_embedding == kEmbedMapsViaWeakCells) { | 3067 if (map_embedding == kEmbedMapsViaWeakCells) { |
3066 HValue* cell = | 3068 HValue* cell = |
3067 Add<HConstant>(Map::WeakCellForMap(type->Classes().Current())); | 3069 Add<HConstant>(Map::WeakCellForMap(type->Classes().Current())); |
3068 HValue* expected_map = Add<HLoadNamedField>( | 3070 HValue* expected_map = Add<HLoadNamedField>( |
3069 cell, nullptr, HObjectAccess::ForWeakCellValue()); | 3071 cell, nullptr, HObjectAccess::ForWeakCellValue()); |
3070 HValue* map = | 3072 HValue* map = |
3071 Add<HLoadNamedField>(value, nullptr, HObjectAccess::ForMap()); | 3073 Add<HLoadNamedField>(value, nullptr, HObjectAccess::ForMap()); |
3072 IfBuilder map_check(this); | 3074 IfBuilder map_check(this); |
3073 map_check.IfNot<HCompareObjectEqAndBranch>(expected_map, map); | 3075 map_check.IfNot<HCompareObjectEqAndBranch>(expected_map, map); |
3074 map_check.ThenDeopt("Unknown map"); | 3076 map_check.ThenDeopt(Deoptimizer::kUnknownMap); |
3075 map_check.End(); | 3077 map_check.End(); |
3076 } else { | 3078 } else { |
3077 DCHECK(map_embedding == kEmbedMapsDirectly); | 3079 DCHECK(map_embedding == kEmbedMapsDirectly); |
3078 Add<HCheckMaps>(value, type->Classes().Current()); | 3080 Add<HCheckMaps>(value, type->Classes().Current()); |
3079 } | 3081 } |
3080 } else { | 3082 } else { |
3081 if_nil.Deopt("Too many undetectable types"); | 3083 if_nil.Deopt(Deoptimizer::kTooManyUndetectableTypes); |
3082 } | 3084 } |
3083 } | 3085 } |
3084 | 3086 |
3085 if_nil.CaptureContinuation(continuation); | 3087 if_nil.CaptureContinuation(continuation); |
3086 } | 3088 } |
3087 | 3089 |
3088 | 3090 |
3089 void HGraphBuilder::BuildCreateAllocationMemento( | 3091 void HGraphBuilder::BuildCreateAllocationMemento( |
3090 HValue* previous_object, | 3092 HValue* previous_object, |
3091 HValue* previous_object_size, | 3093 HValue* previous_object_size, |
(...skipping 3309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6401 } | 6403 } |
6402 | 6404 |
6403 if (current_block() != NULL) Goto(join); | 6405 if (current_block() != NULL) Goto(join); |
6404 set_current_block(if_false); | 6406 set_current_block(if_false); |
6405 } | 6407 } |
6406 | 6408 |
6407 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 6409 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
6408 // know about and do not want to handle ones we've never seen. Otherwise | 6410 // know about and do not want to handle ones we've never seen. Otherwise |
6409 // use a generic IC. | 6411 // use a generic IC. |
6410 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | 6412 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { |
6411 FinishExitWithHardDeoptimization("Unknown map in polymorphic access"); | 6413 FinishExitWithHardDeoptimization( |
| 6414 Deoptimizer::kUnknownMapInPolymorphicAccess); |
6412 } else { | 6415 } else { |
6413 HInstruction* instr = BuildNamedGeneric(access_type, expr, object, name, | 6416 HInstruction* instr = BuildNamedGeneric(access_type, expr, object, name, |
6414 value); | 6417 value); |
6415 AddInstruction(instr); | 6418 AddInstruction(instr); |
6416 if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value); | 6419 if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value); |
6417 | 6420 |
6418 if (join != NULL) { | 6421 if (join != NULL) { |
6419 Goto(join); | 6422 Goto(join); |
6420 } else { | 6423 } else { |
6421 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6424 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6548 | 6551 |
6549 LookupIterator it(global, var->name(), LookupIterator::OWN_SKIP_INTERCEPTOR); | 6552 LookupIterator it(global, var->name(), LookupIterator::OWN_SKIP_INTERCEPTOR); |
6550 GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE); | 6553 GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE); |
6551 if (type == kUseCell) { | 6554 if (type == kUseCell) { |
6552 Handle<PropertyCell> cell = it.GetPropertyCell(); | 6555 Handle<PropertyCell> cell = it.GetPropertyCell(); |
6553 if (cell->type()->IsConstant()) { | 6556 if (cell->type()->IsConstant()) { |
6554 Handle<Object> constant = cell->type()->AsConstant()->Value(); | 6557 Handle<Object> constant = cell->type()->AsConstant()->Value(); |
6555 if (value->IsConstant()) { | 6558 if (value->IsConstant()) { |
6556 HConstant* c_value = HConstant::cast(value); | 6559 HConstant* c_value = HConstant::cast(value); |
6557 if (!constant.is_identical_to(c_value->handle(isolate()))) { | 6560 if (!constant.is_identical_to(c_value->handle(isolate()))) { |
6558 Add<HDeoptimize>("Constant global variable assignment", | 6561 Add<HDeoptimize>(Deoptimizer::kConstantGlobalVariableAssignment, |
6559 Deoptimizer::EAGER); | 6562 Deoptimizer::EAGER); |
6560 } | 6563 } |
6561 } else { | 6564 } else { |
6562 HValue* c_constant = Add<HConstant>(constant); | 6565 HValue* c_constant = Add<HConstant>(constant); |
6563 IfBuilder builder(this); | 6566 IfBuilder builder(this); |
6564 if (constant->IsNumber()) { | 6567 if (constant->IsNumber()) { |
6565 builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ); | 6568 builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ); |
6566 } else { | 6569 } else { |
6567 builder.If<HCompareObjectEqAndBranch>(value, c_constant); | 6570 builder.If<HCompareObjectEqAndBranch>(value, c_constant); |
6568 } | 6571 } |
6569 builder.Then(); | 6572 builder.Then(); |
6570 builder.Else(); | 6573 builder.Else(); |
6571 Add<HDeoptimize>("Constant global variable assignment", | 6574 Add<HDeoptimize>(Deoptimizer::kConstantGlobalVariableAssignment, |
6572 Deoptimizer::EAGER); | 6575 Deoptimizer::EAGER); |
6573 builder.End(); | 6576 builder.End(); |
6574 } | 6577 } |
6575 } | 6578 } |
6576 HInstruction* instr = | 6579 HInstruction* instr = |
6577 Add<HStoreGlobalCell>(value, cell, it.property_details()); | 6580 Add<HStoreGlobalCell>(value, cell, it.property_details()); |
6578 if (instr->HasObservableSideEffects()) { | 6581 if (instr->HasObservableSideEffects()) { |
6579 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6582 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
6580 } | 6583 } |
6581 } else { | 6584 } else { |
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6882 | 6885 |
6883 | 6886 |
6884 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric( | 6887 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric( |
6885 PropertyAccessType access_type, | 6888 PropertyAccessType access_type, |
6886 Expression* expr, | 6889 Expression* expr, |
6887 HValue* object, | 6890 HValue* object, |
6888 Handle<String> name, | 6891 Handle<String> name, |
6889 HValue* value, | 6892 HValue* value, |
6890 bool is_uninitialized) { | 6893 bool is_uninitialized) { |
6891 if (is_uninitialized) { | 6894 if (is_uninitialized) { |
6892 Add<HDeoptimize>("Insufficient type feedback for generic named access", | 6895 Add<HDeoptimize>( |
6893 Deoptimizer::SOFT); | 6896 Deoptimizer::kInsufficientTypeFeedbackForGenericNamedAccess, |
| 6897 Deoptimizer::SOFT); |
6894 } | 6898 } |
6895 if (access_type == LOAD) { | 6899 if (access_type == LOAD) { |
6896 HLoadNamedGeneric* result = New<HLoadNamedGeneric>(object, name); | 6900 HLoadNamedGeneric* result = New<HLoadNamedGeneric>(object, name); |
6897 if (FLAG_vector_ics) { | 6901 if (FLAG_vector_ics) { |
6898 Handle<SharedFunctionInfo> current_shared = | 6902 Handle<SharedFunctionInfo> current_shared = |
6899 function_state()->compilation_info()->shared_info(); | 6903 function_state()->compilation_info()->shared_info(); |
6900 Handle<TypeFeedbackVector> vector = | 6904 Handle<TypeFeedbackVector> vector = |
6901 handle(current_shared->feedback_vector(), isolate()); | 6905 handle(current_shared->feedback_vector(), isolate()); |
6902 FeedbackVectorICSlot slot = expr->AsProperty()->PropertyFeedbackSlot(); | 6906 FeedbackVectorICSlot slot = expr->AsProperty()->PropertyFeedbackSlot(); |
6903 result->SetVectorAndSlot(vector, slot); | 6907 result->SetVectorAndSlot(vector, slot); |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7183 set_current_block(other_map); | 7187 set_current_block(other_map); |
7184 } | 7188 } |
7185 | 7189 |
7186 // Ensure that we visited at least one map above that goes to join. This is | 7190 // Ensure that we visited at least one map above that goes to join. This is |
7187 // necessary because FinishExitWithHardDeoptimization does an AbnormalExit | 7191 // necessary because FinishExitWithHardDeoptimization does an AbnormalExit |
7188 // rather than joining the join block. If this becomes an issue, insert a | 7192 // rather than joining the join block. If this becomes an issue, insert a |
7189 // generic access in the case length() == 0. | 7193 // generic access in the case length() == 0. |
7190 DCHECK(join->predecessors()->length() > 0); | 7194 DCHECK(join->predecessors()->length() > 0); |
7191 // Deopt if none of the cases matched. | 7195 // Deopt if none of the cases matched. |
7192 NoObservableSideEffectsScope scope(this); | 7196 NoObservableSideEffectsScope scope(this); |
7193 FinishExitWithHardDeoptimization("Unknown map in polymorphic element access"); | 7197 FinishExitWithHardDeoptimization( |
| 7198 Deoptimizer::kUnknownMapInPolymorphicElementAccess); |
7194 set_current_block(join); | 7199 set_current_block(join); |
7195 return access_type == STORE ? val : Pop(); | 7200 return access_type == STORE ? val : Pop(); |
7196 } | 7201 } |
7197 | 7202 |
7198 | 7203 |
7199 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( | 7204 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( |
7200 HValue* obj, HValue* key, HValue* val, Expression* expr, BailoutId ast_id, | 7205 HValue* obj, HValue* key, HValue* val, Expression* expr, BailoutId ast_id, |
7201 BailoutId return_id, PropertyAccessType access_type, | 7206 BailoutId return_id, PropertyAccessType access_type, |
7202 bool* has_side_effects) { | 7207 bool* has_side_effects) { |
7203 // TODO(mvstanton): This optimization causes trouble for vector-based | 7208 // TODO(mvstanton): This optimization causes trouble for vector-based |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7278 obj, key, val, NULL, map, access_type, expr->GetStoreMode()); | 7283 obj, key, val, NULL, map, access_type, expr->GetStoreMode()); |
7279 } | 7284 } |
7280 } else if (!force_generic && (types != NULL && !types->is_empty())) { | 7285 } else if (!force_generic && (types != NULL && !types->is_empty())) { |
7281 return HandlePolymorphicElementAccess( | 7286 return HandlePolymorphicElementAccess( |
7282 expr, obj, key, val, types, access_type, | 7287 expr, obj, key, val, types, access_type, |
7283 expr->GetStoreMode(), has_side_effects); | 7288 expr->GetStoreMode(), has_side_effects); |
7284 } else { | 7289 } else { |
7285 if (access_type == STORE) { | 7290 if (access_type == STORE) { |
7286 if (expr->IsAssignment() && | 7291 if (expr->IsAssignment() && |
7287 expr->AsAssignment()->HasNoTypeInformation()) { | 7292 expr->AsAssignment()->HasNoTypeInformation()) { |
7288 Add<HDeoptimize>("Insufficient type feedback for keyed store", | 7293 Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedStore, |
7289 Deoptimizer::SOFT); | 7294 Deoptimizer::SOFT); |
7290 } | 7295 } |
7291 } else { | 7296 } else { |
7292 if (expr->AsProperty()->HasNoTypeInformation()) { | 7297 if (expr->AsProperty()->HasNoTypeInformation()) { |
7293 Add<HDeoptimize>("Insufficient type feedback for keyed load", | 7298 Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedLoad, |
7294 Deoptimizer::SOFT); | 7299 Deoptimizer::SOFT); |
7295 } | 7300 } |
7296 } | 7301 } |
7297 instr = AddInstruction(BuildKeyedGeneric(access_type, expr, obj, key, val)); | 7302 instr = AddInstruction(BuildKeyedGeneric(access_type, expr, obj, key, val)); |
7298 } | 7303 } |
7299 *has_side_effects = instr->HasObservableSideEffects(); | 7304 *has_side_effects = instr->HasObservableSideEffects(); |
7300 return instr; | 7305 return instr; |
7301 } | 7306 } |
7302 | 7307 |
7303 | 7308 |
(...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7728 } | 7733 } |
7729 | 7734 |
7730 if (current_block() != NULL) Goto(join); | 7735 if (current_block() != NULL) Goto(join); |
7731 set_current_block(if_false); | 7736 set_current_block(if_false); |
7732 } | 7737 } |
7733 | 7738 |
7734 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 7739 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
7735 // know about and do not want to handle ones we've never seen. Otherwise | 7740 // know about and do not want to handle ones we've never seen. Otherwise |
7736 // use a generic IC. | 7741 // use a generic IC. |
7737 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { | 7742 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { |
7738 FinishExitWithHardDeoptimization("Unknown map in polymorphic call"); | 7743 FinishExitWithHardDeoptimization(Deoptimizer::kUnknownMapInPolymorphicCall); |
7739 } else { | 7744 } else { |
7740 Property* prop = expr->expression()->AsProperty(); | 7745 Property* prop = expr->expression()->AsProperty(); |
7741 HInstruction* function = BuildNamedGeneric( | 7746 HInstruction* function = BuildNamedGeneric( |
7742 LOAD, prop, receiver, name, NULL, prop->IsUninitialized()); | 7747 LOAD, prop, receiver, name, NULL, prop->IsUninitialized()); |
7743 AddInstruction(function); | 7748 AddInstruction(function); |
7744 Push(function); | 7749 Push(function); |
7745 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 7750 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); |
7746 | 7751 |
7747 environment()->SetExpressionStackAt(1, function); | 7752 environment()->SetExpressionStackAt(1, function); |
7748 environment()->SetExpressionStackAt(0, receiver); | 7753 environment()->SetExpressionStackAt(0, receiver); |
(...skipping 1485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9234 return; | 9239 return; |
9235 } else { | 9240 } else { |
9236 call = BuildCallConstantFunction(known_function, argument_count); | 9241 call = BuildCallConstantFunction(known_function, argument_count); |
9237 } | 9242 } |
9238 | 9243 |
9239 } else { | 9244 } else { |
9240 ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED; | 9245 ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED; |
9241 if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) { | 9246 if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) { |
9242 // We have to use EAGER deoptimization here because Deoptimizer::SOFT | 9247 // We have to use EAGER deoptimization here because Deoptimizer::SOFT |
9243 // gets ignored by the always-opt flag, which leads to incorrect code. | 9248 // gets ignored by the always-opt flag, which leads to incorrect code. |
9244 Add<HDeoptimize>("Insufficient type feedback for call with arguments", | 9249 Add<HDeoptimize>( |
9245 Deoptimizer::EAGER); | 9250 Deoptimizer::kInsufficientTypeFeedbackForCallWithArguments, |
| 9251 Deoptimizer::EAGER); |
9246 arguments_flag = ARGUMENTS_FAKED; | 9252 arguments_flag = ARGUMENTS_FAKED; |
9247 } | 9253 } |
9248 | 9254 |
9249 // Push the function under the receiver. | 9255 // Push the function under the receiver. |
9250 environment()->SetExpressionStackAt(0, function); | 9256 environment()->SetExpressionStackAt(0, function); |
9251 Push(receiver); | 9257 Push(receiver); |
9252 | 9258 |
9253 CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag)); | 9259 CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag)); |
9254 CallFunctionFlags flags = receiver->type().IsJSObject() | 9260 CallFunctionFlags flags = receiver->type().IsJSObject() |
9255 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD; | 9261 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD; |
(...skipping 1209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10465 Representation left_rep = Representation::FromType(left_type); | 10471 Representation left_rep = Representation::FromType(left_type); |
10466 Representation right_rep = Representation::FromType(right_type); | 10472 Representation right_rep = Representation::FromType(right_type); |
10467 | 10473 |
10468 bool maybe_string_add = op == Token::ADD && | 10474 bool maybe_string_add = op == Token::ADD && |
10469 (left_type->Maybe(Type::String()) || | 10475 (left_type->Maybe(Type::String()) || |
10470 left_type->Maybe(Type::Receiver()) || | 10476 left_type->Maybe(Type::Receiver()) || |
10471 right_type->Maybe(Type::String()) || | 10477 right_type->Maybe(Type::String()) || |
10472 right_type->Maybe(Type::Receiver())); | 10478 right_type->Maybe(Type::Receiver())); |
10473 | 10479 |
10474 if (!left_type->IsInhabited()) { | 10480 if (!left_type->IsInhabited()) { |
10475 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", | 10481 Add<HDeoptimize>( |
10476 Deoptimizer::SOFT); | 10482 Deoptimizer::kInsufficientTypeFeedbackForLHSOfBinaryOperation, |
| 10483 Deoptimizer::SOFT); |
10477 // TODO(rossberg): we should be able to get rid of non-continuous | 10484 // TODO(rossberg): we should be able to get rid of non-continuous |
10478 // defaults. | 10485 // defaults. |
10479 left_type = Type::Any(zone()); | 10486 left_type = Type::Any(zone()); |
10480 } else { | 10487 } else { |
10481 if (!maybe_string_add) left = TruncateToNumber(left, &left_type); | 10488 if (!maybe_string_add) left = TruncateToNumber(left, &left_type); |
10482 left_rep = Representation::FromType(left_type); | 10489 left_rep = Representation::FromType(left_type); |
10483 } | 10490 } |
10484 | 10491 |
10485 if (!right_type->IsInhabited()) { | 10492 if (!right_type->IsInhabited()) { |
10486 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", | 10493 Add<HDeoptimize>( |
10487 Deoptimizer::SOFT); | 10494 Deoptimizer::kInsufficientTypeFeedbackForRHSOfBinaryOperation, |
| 10495 Deoptimizer::SOFT); |
10488 right_type = Type::Any(zone()); | 10496 right_type = Type::Any(zone()); |
10489 } else { | 10497 } else { |
10490 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); | 10498 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); |
10491 right_rep = Representation::FromType(right_type); | 10499 right_rep = Representation::FromType(right_type); |
10492 } | 10500 } |
10493 | 10501 |
10494 // Special case for string addition here. | 10502 // Special case for string addition here. |
10495 if (op == Token::ADD && | 10503 if (op == Token::ADD && |
10496 (left_type->Is(Type::String()) || right_type->Is(Type::String()))) { | 10504 (left_type->Is(Type::String()) || right_type->Is(Type::String()))) { |
10497 // Validate type feedback for left argument. | 10505 // Validate type feedback for left argument. |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10597 instr = AddUncasted<HMul>(left, right); | 10605 instr = AddUncasted<HMul>(left, right); |
10598 break; | 10606 break; |
10599 case Token::MOD: { | 10607 case Token::MOD: { |
10600 if (fixed_right_arg.has_value && | 10608 if (fixed_right_arg.has_value && |
10601 !right->EqualsInteger32Constant(fixed_right_arg.value)) { | 10609 !right->EqualsInteger32Constant(fixed_right_arg.value)) { |
10602 HConstant* fixed_right = Add<HConstant>( | 10610 HConstant* fixed_right = Add<HConstant>( |
10603 static_cast<int>(fixed_right_arg.value)); | 10611 static_cast<int>(fixed_right_arg.value)); |
10604 IfBuilder if_same(this); | 10612 IfBuilder if_same(this); |
10605 if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ); | 10613 if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ); |
10606 if_same.Then(); | 10614 if_same.Then(); |
10607 if_same.ElseDeopt("Unexpected RHS of binary operation"); | 10615 if_same.ElseDeopt(Deoptimizer::kUnexpectedRHSOfBinaryOperation); |
10608 right = fixed_right; | 10616 right = fixed_right; |
10609 } | 10617 } |
10610 instr = AddUncasted<HMod>(left, right); | 10618 instr = AddUncasted<HMod>(left, right); |
10611 break; | 10619 break; |
10612 } | 10620 } |
10613 case Token::DIV: | 10621 case Token::DIV: |
10614 instr = AddUncasted<HDiv>(left, right); | 10622 instr = AddUncasted<HDiv>(left, right); |
10615 break; | 10623 break; |
10616 case Token::BIT_XOR: | 10624 case Token::BIT_XOR: |
10617 case Token::BIT_AND: | 10625 case Token::BIT_AND: |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10971 Type* left_type, | 10979 Type* left_type, |
10972 Type* right_type, | 10980 Type* right_type, |
10973 Type* combined_type, | 10981 Type* combined_type, |
10974 HSourcePosition left_position, | 10982 HSourcePosition left_position, |
10975 HSourcePosition right_position, | 10983 HSourcePosition right_position, |
10976 PushBeforeSimulateBehavior push_sim_result, | 10984 PushBeforeSimulateBehavior push_sim_result, |
10977 BailoutId bailout_id) { | 10985 BailoutId bailout_id) { |
10978 // Cases handled below depend on collected type feedback. They should | 10986 // Cases handled below depend on collected type feedback. They should |
10979 // soft deoptimize when there is no type feedback. | 10987 // soft deoptimize when there is no type feedback. |
10980 if (!combined_type->IsInhabited()) { | 10988 if (!combined_type->IsInhabited()) { |
10981 Add<HDeoptimize>("Insufficient type feedback for combined type " | 10989 Add<HDeoptimize>( |
10982 "of binary operation", | 10990 Deoptimizer::kInsufficientTypeFeedbackForCombinedTypeOfBinaryOperation, |
10983 Deoptimizer::SOFT); | 10991 Deoptimizer::SOFT); |
10984 combined_type = left_type = right_type = Type::Any(zone()); | 10992 combined_type = left_type = right_type = Type::Any(zone()); |
10985 } | 10993 } |
10986 | 10994 |
10987 Representation left_rep = Representation::FromType(left_type); | 10995 Representation left_rep = Representation::FromType(left_type); |
10988 Representation right_rep = Representation::FromType(right_type); | 10996 Representation right_rep = Representation::FromType(right_type); |
10989 Representation combined_rep = Representation::FromType(combined_type); | 10997 Representation combined_rep = Representation::FromType(combined_type); |
10990 | 10998 |
10991 if (combined_type->Is(Type::Receiver())) { | 10999 if (combined_type->Is(Type::Receiver())) { |
10992 if (Token::IsEqualityOp(op)) { | 11000 if (Token::IsEqualityOp(op)) { |
10993 // HCompareObjectEqAndBranch can only deal with object, so | 11001 // HCompareObjectEqAndBranch can only deal with object, so |
10994 // exclude numbers. | 11002 // exclude numbers. |
10995 if ((left->IsConstant() && | 11003 if ((left->IsConstant() && |
10996 HConstant::cast(left)->HasNumberValue()) || | 11004 HConstant::cast(left)->HasNumberValue()) || |
10997 (right->IsConstant() && | 11005 (right->IsConstant() && |
10998 HConstant::cast(right)->HasNumberValue())) { | 11006 HConstant::cast(right)->HasNumberValue())) { |
10999 Add<HDeoptimize>("Type mismatch between feedback and constant", | 11007 Add<HDeoptimize>(Deoptimizer::kTypeMismatchBetweenFeedbackAndConstant, |
11000 Deoptimizer::SOFT); | 11008 Deoptimizer::SOFT); |
11001 // The caller expects a branch instruction, so make it happy. | 11009 // The caller expects a branch instruction, so make it happy. |
11002 return New<HBranch>(graph()->GetConstantTrue()); | 11010 return New<HBranch>(graph()->GetConstantTrue()); |
11003 } | 11011 } |
11004 // Can we get away with map check and not instance type check? | 11012 // Can we get away with map check and not instance type check? |
11005 HValue* operand_to_check = | 11013 HValue* operand_to_check = |
11006 left->block()->block_id() < right->block()->block_id() ? left : right; | 11014 left->block()->block_id() < right->block()->block_id() ? left : right; |
11007 if (combined_type->IsClass()) { | 11015 if (combined_type->IsClass()) { |
11008 Handle<Map> map = combined_type->AsClass()->Map(); | 11016 Handle<Map> map = combined_type->AsClass()->Map(); |
11009 AddCheckMap(operand_to_check, map); | 11017 AddCheckMap(operand_to_check, map); |
(...skipping 17 matching lines...) Expand all Loading... |
11027 return NULL; | 11035 return NULL; |
11028 } | 11036 } |
11029 } else if (combined_type->Is(Type::InternalizedString()) && | 11037 } else if (combined_type->Is(Type::InternalizedString()) && |
11030 Token::IsEqualityOp(op)) { | 11038 Token::IsEqualityOp(op)) { |
11031 // If we have a constant argument, it should be consistent with the type | 11039 // If we have a constant argument, it should be consistent with the type |
11032 // feedback (otherwise we fail assertions in HCompareObjectEqAndBranch). | 11040 // feedback (otherwise we fail assertions in HCompareObjectEqAndBranch). |
11033 if ((left->IsConstant() && | 11041 if ((left->IsConstant() && |
11034 !HConstant::cast(left)->HasInternalizedStringValue()) || | 11042 !HConstant::cast(left)->HasInternalizedStringValue()) || |
11035 (right->IsConstant() && | 11043 (right->IsConstant() && |
11036 !HConstant::cast(right)->HasInternalizedStringValue())) { | 11044 !HConstant::cast(right)->HasInternalizedStringValue())) { |
11037 Add<HDeoptimize>("Type mismatch between feedback and constant", | 11045 Add<HDeoptimize>(Deoptimizer::kTypeMismatchBetweenFeedbackAndConstant, |
11038 Deoptimizer::SOFT); | 11046 Deoptimizer::SOFT); |
11039 // The caller expects a branch instruction, so make it happy. | 11047 // The caller expects a branch instruction, so make it happy. |
11040 return New<HBranch>(graph()->GetConstantTrue()); | 11048 return New<HBranch>(graph()->GetConstantTrue()); |
11041 } | 11049 } |
11042 BuildCheckHeapObject(left); | 11050 BuildCheckHeapObject(left); |
11043 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING); | 11051 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING); |
11044 BuildCheckHeapObject(right); | 11052 BuildCheckHeapObject(right); |
11045 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING); | 11053 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING); |
11046 HCompareObjectEqAndBranch* result = | 11054 HCompareObjectEqAndBranch* result = |
11047 New<HCompareObjectEqAndBranch>(left, right); | 11055 New<HCompareObjectEqAndBranch>(left, right); |
(...skipping 2428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13476 if (ShouldProduceTraceOutput()) { | 13484 if (ShouldProduceTraceOutput()) { |
13477 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13485 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
13478 } | 13486 } |
13479 | 13487 |
13480 #ifdef DEBUG | 13488 #ifdef DEBUG |
13481 graph_->Verify(false); // No full verify. | 13489 graph_->Verify(false); // No full verify. |
13482 #endif | 13490 #endif |
13483 } | 13491 } |
13484 | 13492 |
13485 } } // namespace v8::internal | 13493 } } // namespace v8::internal |
OLD | NEW |