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 3312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6404 } | 6406 } |
6405 | 6407 |
6406 if (current_block() != NULL) Goto(join); | 6408 if (current_block() != NULL) Goto(join); |
6407 set_current_block(if_false); | 6409 set_current_block(if_false); |
6408 } | 6410 } |
6409 | 6411 |
6410 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 6412 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
6411 // know about and do not want to handle ones we've never seen. Otherwise | 6413 // know about and do not want to handle ones we've never seen. Otherwise |
6412 // use a generic IC. | 6414 // use a generic IC. |
6413 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | 6415 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { |
6414 FinishExitWithHardDeoptimization("Unknown map in polymorphic access"); | 6416 FinishExitWithHardDeoptimization( |
| 6417 Deoptimizer::kUnknownMapInPolymorphicAccess); |
6415 } else { | 6418 } else { |
6416 HInstruction* instr = BuildNamedGeneric(access_type, expr, object, name, | 6419 HInstruction* instr = BuildNamedGeneric(access_type, expr, object, name, |
6417 value); | 6420 value); |
6418 AddInstruction(instr); | 6421 AddInstruction(instr); |
6419 if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value); | 6422 if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value); |
6420 | 6423 |
6421 if (join != NULL) { | 6424 if (join != NULL) { |
6422 Goto(join); | 6425 Goto(join); |
6423 } else { | 6426 } else { |
6424 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6427 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6551 | 6554 |
6552 LookupIterator it(global, var->name(), LookupIterator::OWN_SKIP_INTERCEPTOR); | 6555 LookupIterator it(global, var->name(), LookupIterator::OWN_SKIP_INTERCEPTOR); |
6553 GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE); | 6556 GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE); |
6554 if (type == kUseCell) { | 6557 if (type == kUseCell) { |
6555 Handle<PropertyCell> cell = it.GetPropertyCell(); | 6558 Handle<PropertyCell> cell = it.GetPropertyCell(); |
6556 if (cell->type()->IsConstant()) { | 6559 if (cell->type()->IsConstant()) { |
6557 Handle<Object> constant = cell->type()->AsConstant()->Value(); | 6560 Handle<Object> constant = cell->type()->AsConstant()->Value(); |
6558 if (value->IsConstant()) { | 6561 if (value->IsConstant()) { |
6559 HConstant* c_value = HConstant::cast(value); | 6562 HConstant* c_value = HConstant::cast(value); |
6560 if (!constant.is_identical_to(c_value->handle(isolate()))) { | 6563 if (!constant.is_identical_to(c_value->handle(isolate()))) { |
6561 Add<HDeoptimize>("Constant global variable assignment", | 6564 Add<HDeoptimize>(Deoptimizer::kConstantGlobalVariableAssignment, |
6562 Deoptimizer::EAGER); | 6565 Deoptimizer::EAGER); |
6563 } | 6566 } |
6564 } else { | 6567 } else { |
6565 HValue* c_constant = Add<HConstant>(constant); | 6568 HValue* c_constant = Add<HConstant>(constant); |
6566 IfBuilder builder(this); | 6569 IfBuilder builder(this); |
6567 if (constant->IsNumber()) { | 6570 if (constant->IsNumber()) { |
6568 builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ); | 6571 builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ); |
6569 } else { | 6572 } else { |
6570 builder.If<HCompareObjectEqAndBranch>(value, c_constant); | 6573 builder.If<HCompareObjectEqAndBranch>(value, c_constant); |
6571 } | 6574 } |
6572 builder.Then(); | 6575 builder.Then(); |
6573 builder.Else(); | 6576 builder.Else(); |
6574 Add<HDeoptimize>("Constant global variable assignment", | 6577 Add<HDeoptimize>(Deoptimizer::kConstantGlobalVariableAssignment, |
6575 Deoptimizer::EAGER); | 6578 Deoptimizer::EAGER); |
6576 builder.End(); | 6579 builder.End(); |
6577 } | 6580 } |
6578 } | 6581 } |
6579 HInstruction* instr = | 6582 HInstruction* instr = |
6580 Add<HStoreGlobalCell>(value, cell, it.property_details()); | 6583 Add<HStoreGlobalCell>(value, cell, it.property_details()); |
6581 if (instr->HasObservableSideEffects()) { | 6584 if (instr->HasObservableSideEffects()) { |
6582 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6585 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
6583 } | 6586 } |
6584 } else { | 6587 } else { |
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6885 | 6888 |
6886 | 6889 |
6887 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric( | 6890 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric( |
6888 PropertyAccessType access_type, | 6891 PropertyAccessType access_type, |
6889 Expression* expr, | 6892 Expression* expr, |
6890 HValue* object, | 6893 HValue* object, |
6891 Handle<String> name, | 6894 Handle<String> name, |
6892 HValue* value, | 6895 HValue* value, |
6893 bool is_uninitialized) { | 6896 bool is_uninitialized) { |
6894 if (is_uninitialized) { | 6897 if (is_uninitialized) { |
6895 Add<HDeoptimize>("Insufficient type feedback for generic named access", | 6898 Add<HDeoptimize>( |
6896 Deoptimizer::SOFT); | 6899 Deoptimizer::kInsufficientTypeFeedbackForGenericNamedAccess, |
| 6900 Deoptimizer::SOFT); |
6897 } | 6901 } |
6898 if (access_type == LOAD) { | 6902 if (access_type == LOAD) { |
6899 HLoadNamedGeneric* result = New<HLoadNamedGeneric>(object, name); | 6903 HLoadNamedGeneric* result = New<HLoadNamedGeneric>(object, name); |
6900 if (FLAG_vector_ics) { | 6904 if (FLAG_vector_ics) { |
6901 Handle<SharedFunctionInfo> current_shared = | 6905 Handle<SharedFunctionInfo> current_shared = |
6902 function_state()->compilation_info()->shared_info(); | 6906 function_state()->compilation_info()->shared_info(); |
6903 Handle<TypeFeedbackVector> vector = | 6907 Handle<TypeFeedbackVector> vector = |
6904 handle(current_shared->feedback_vector(), isolate()); | 6908 handle(current_shared->feedback_vector(), isolate()); |
6905 FeedbackVectorICSlot slot = expr->AsProperty()->PropertyFeedbackSlot(); | 6909 FeedbackVectorICSlot slot = expr->AsProperty()->PropertyFeedbackSlot(); |
6906 result->SetVectorAndSlot(vector, slot); | 6910 result->SetVectorAndSlot(vector, slot); |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7186 set_current_block(other_map); | 7190 set_current_block(other_map); |
7187 } | 7191 } |
7188 | 7192 |
7189 // Ensure that we visited at least one map above that goes to join. This is | 7193 // Ensure that we visited at least one map above that goes to join. This is |
7190 // necessary because FinishExitWithHardDeoptimization does an AbnormalExit | 7194 // necessary because FinishExitWithHardDeoptimization does an AbnormalExit |
7191 // rather than joining the join block. If this becomes an issue, insert a | 7195 // rather than joining the join block. If this becomes an issue, insert a |
7192 // generic access in the case length() == 0. | 7196 // generic access in the case length() == 0. |
7193 DCHECK(join->predecessors()->length() > 0); | 7197 DCHECK(join->predecessors()->length() > 0); |
7194 // Deopt if none of the cases matched. | 7198 // Deopt if none of the cases matched. |
7195 NoObservableSideEffectsScope scope(this); | 7199 NoObservableSideEffectsScope scope(this); |
7196 FinishExitWithHardDeoptimization("Unknown map in polymorphic element access"); | 7200 FinishExitWithHardDeoptimization( |
| 7201 Deoptimizer::kUnknownMapInPolymorphicElementAccess); |
7197 set_current_block(join); | 7202 set_current_block(join); |
7198 return access_type == STORE ? val : Pop(); | 7203 return access_type == STORE ? val : Pop(); |
7199 } | 7204 } |
7200 | 7205 |
7201 | 7206 |
7202 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( | 7207 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( |
7203 HValue* obj, HValue* key, HValue* val, Expression* expr, BailoutId ast_id, | 7208 HValue* obj, HValue* key, HValue* val, Expression* expr, BailoutId ast_id, |
7204 BailoutId return_id, PropertyAccessType access_type, | 7209 BailoutId return_id, PropertyAccessType access_type, |
7205 bool* has_side_effects) { | 7210 bool* has_side_effects) { |
7206 // TODO(mvstanton): This optimization causes trouble for vector-based | 7211 // TODO(mvstanton): This optimization causes trouble for vector-based |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7281 obj, key, val, NULL, map, access_type, expr->GetStoreMode()); | 7286 obj, key, val, NULL, map, access_type, expr->GetStoreMode()); |
7282 } | 7287 } |
7283 } else if (!force_generic && (types != NULL && !types->is_empty())) { | 7288 } else if (!force_generic && (types != NULL && !types->is_empty())) { |
7284 return HandlePolymorphicElementAccess( | 7289 return HandlePolymorphicElementAccess( |
7285 expr, obj, key, val, types, access_type, | 7290 expr, obj, key, val, types, access_type, |
7286 expr->GetStoreMode(), has_side_effects); | 7291 expr->GetStoreMode(), has_side_effects); |
7287 } else { | 7292 } else { |
7288 if (access_type == STORE) { | 7293 if (access_type == STORE) { |
7289 if (expr->IsAssignment() && | 7294 if (expr->IsAssignment() && |
7290 expr->AsAssignment()->HasNoTypeInformation()) { | 7295 expr->AsAssignment()->HasNoTypeInformation()) { |
7291 Add<HDeoptimize>("Insufficient type feedback for keyed store", | 7296 Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedStore, |
7292 Deoptimizer::SOFT); | 7297 Deoptimizer::SOFT); |
7293 } | 7298 } |
7294 } else { | 7299 } else { |
7295 if (expr->AsProperty()->HasNoTypeInformation()) { | 7300 if (expr->AsProperty()->HasNoTypeInformation()) { |
7296 Add<HDeoptimize>("Insufficient type feedback for keyed load", | 7301 Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedLoad, |
7297 Deoptimizer::SOFT); | 7302 Deoptimizer::SOFT); |
7298 } | 7303 } |
7299 } | 7304 } |
7300 instr = AddInstruction(BuildKeyedGeneric(access_type, expr, obj, key, val)); | 7305 instr = AddInstruction(BuildKeyedGeneric(access_type, expr, obj, key, val)); |
7301 } | 7306 } |
7302 *has_side_effects = instr->HasObservableSideEffects(); | 7307 *has_side_effects = instr->HasObservableSideEffects(); |
7303 return instr; | 7308 return instr; |
7304 } | 7309 } |
7305 | 7310 |
7306 | 7311 |
(...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7731 } | 7736 } |
7732 | 7737 |
7733 if (current_block() != NULL) Goto(join); | 7738 if (current_block() != NULL) Goto(join); |
7734 set_current_block(if_false); | 7739 set_current_block(if_false); |
7735 } | 7740 } |
7736 | 7741 |
7737 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 7742 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
7738 // know about and do not want to handle ones we've never seen. Otherwise | 7743 // know about and do not want to handle ones we've never seen. Otherwise |
7739 // use a generic IC. | 7744 // use a generic IC. |
7740 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { | 7745 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { |
7741 FinishExitWithHardDeoptimization("Unknown map in polymorphic call"); | 7746 FinishExitWithHardDeoptimization(Deoptimizer::kUnknownMapInPolymorphicCall); |
7742 } else { | 7747 } else { |
7743 Property* prop = expr->expression()->AsProperty(); | 7748 Property* prop = expr->expression()->AsProperty(); |
7744 HInstruction* function = BuildNamedGeneric( | 7749 HInstruction* function = BuildNamedGeneric( |
7745 LOAD, prop, receiver, name, NULL, prop->IsUninitialized()); | 7750 LOAD, prop, receiver, name, NULL, prop->IsUninitialized()); |
7746 AddInstruction(function); | 7751 AddInstruction(function); |
7747 Push(function); | 7752 Push(function); |
7748 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 7753 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); |
7749 | 7754 |
7750 environment()->SetExpressionStackAt(1, function); | 7755 environment()->SetExpressionStackAt(1, function); |
7751 environment()->SetExpressionStackAt(0, receiver); | 7756 environment()->SetExpressionStackAt(0, receiver); |
(...skipping 1488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9240 return; | 9245 return; |
9241 } else { | 9246 } else { |
9242 call = BuildCallConstantFunction(known_function, argument_count); | 9247 call = BuildCallConstantFunction(known_function, argument_count); |
9243 } | 9248 } |
9244 | 9249 |
9245 } else { | 9250 } else { |
9246 ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED; | 9251 ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED; |
9247 if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) { | 9252 if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) { |
9248 // We have to use EAGER deoptimization here because Deoptimizer::SOFT | 9253 // We have to use EAGER deoptimization here because Deoptimizer::SOFT |
9249 // gets ignored by the always-opt flag, which leads to incorrect code. | 9254 // gets ignored by the always-opt flag, which leads to incorrect code. |
9250 Add<HDeoptimize>("Insufficient type feedback for call with arguments", | 9255 Add<HDeoptimize>( |
9251 Deoptimizer::EAGER); | 9256 Deoptimizer::kInsufficientTypeFeedbackForCallWithArguments, |
| 9257 Deoptimizer::EAGER); |
9252 arguments_flag = ARGUMENTS_FAKED; | 9258 arguments_flag = ARGUMENTS_FAKED; |
9253 } | 9259 } |
9254 | 9260 |
9255 // Push the function under the receiver. | 9261 // Push the function under the receiver. |
9256 environment()->SetExpressionStackAt(0, function); | 9262 environment()->SetExpressionStackAt(0, function); |
9257 Push(receiver); | 9263 Push(receiver); |
9258 | 9264 |
9259 CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag)); | 9265 CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag)); |
9260 CallFunctionFlags flags = receiver->type().IsJSObject() | 9266 CallFunctionFlags flags = receiver->type().IsJSObject() |
9261 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD; | 9267 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD; |
(...skipping 1197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10459 Representation left_rep = Representation::FromType(left_type); | 10465 Representation left_rep = Representation::FromType(left_type); |
10460 Representation right_rep = Representation::FromType(right_type); | 10466 Representation right_rep = Representation::FromType(right_type); |
10461 | 10467 |
10462 bool maybe_string_add = op == Token::ADD && | 10468 bool maybe_string_add = op == Token::ADD && |
10463 (left_type->Maybe(Type::String()) || | 10469 (left_type->Maybe(Type::String()) || |
10464 left_type->Maybe(Type::Receiver()) || | 10470 left_type->Maybe(Type::Receiver()) || |
10465 right_type->Maybe(Type::String()) || | 10471 right_type->Maybe(Type::String()) || |
10466 right_type->Maybe(Type::Receiver())); | 10472 right_type->Maybe(Type::Receiver())); |
10467 | 10473 |
10468 if (!left_type->IsInhabited()) { | 10474 if (!left_type->IsInhabited()) { |
10469 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", | 10475 Add<HDeoptimize>( |
10470 Deoptimizer::SOFT); | 10476 Deoptimizer::kInsufficientTypeFeedbackForLHSOfBinaryOperation, |
| 10477 Deoptimizer::SOFT); |
10471 // TODO(rossberg): we should be able to get rid of non-continuous | 10478 // TODO(rossberg): we should be able to get rid of non-continuous |
10472 // defaults. | 10479 // defaults. |
10473 left_type = Type::Any(zone()); | 10480 left_type = Type::Any(zone()); |
10474 } else { | 10481 } else { |
10475 if (!maybe_string_add) left = TruncateToNumber(left, &left_type); | 10482 if (!maybe_string_add) left = TruncateToNumber(left, &left_type); |
10476 left_rep = Representation::FromType(left_type); | 10483 left_rep = Representation::FromType(left_type); |
10477 } | 10484 } |
10478 | 10485 |
10479 if (!right_type->IsInhabited()) { | 10486 if (!right_type->IsInhabited()) { |
10480 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", | 10487 Add<HDeoptimize>( |
10481 Deoptimizer::SOFT); | 10488 Deoptimizer::kInsufficientTypeFeedbackForRHSOfBinaryOperation, |
| 10489 Deoptimizer::SOFT); |
10482 right_type = Type::Any(zone()); | 10490 right_type = Type::Any(zone()); |
10483 } else { | 10491 } else { |
10484 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); | 10492 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); |
10485 right_rep = Representation::FromType(right_type); | 10493 right_rep = Representation::FromType(right_type); |
10486 } | 10494 } |
10487 | 10495 |
10488 // Special case for string addition here. | 10496 // Special case for string addition here. |
10489 if (op == Token::ADD && | 10497 if (op == Token::ADD && |
10490 (left_type->Is(Type::String()) || right_type->Is(Type::String()))) { | 10498 (left_type->Is(Type::String()) || right_type->Is(Type::String()))) { |
10491 // Validate type feedback for left argument. | 10499 // Validate type feedback for left argument. |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10591 instr = AddUncasted<HMul>(left, right); | 10599 instr = AddUncasted<HMul>(left, right); |
10592 break; | 10600 break; |
10593 case Token::MOD: { | 10601 case Token::MOD: { |
10594 if (fixed_right_arg.has_value && | 10602 if (fixed_right_arg.has_value && |
10595 !right->EqualsInteger32Constant(fixed_right_arg.value)) { | 10603 !right->EqualsInteger32Constant(fixed_right_arg.value)) { |
10596 HConstant* fixed_right = Add<HConstant>( | 10604 HConstant* fixed_right = Add<HConstant>( |
10597 static_cast<int>(fixed_right_arg.value)); | 10605 static_cast<int>(fixed_right_arg.value)); |
10598 IfBuilder if_same(this); | 10606 IfBuilder if_same(this); |
10599 if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ); | 10607 if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ); |
10600 if_same.Then(); | 10608 if_same.Then(); |
10601 if_same.ElseDeopt("Unexpected RHS of binary operation"); | 10609 if_same.ElseDeopt(Deoptimizer::kUnexpectedRHSOfBinaryOperation); |
10602 right = fixed_right; | 10610 right = fixed_right; |
10603 } | 10611 } |
10604 instr = AddUncasted<HMod>(left, right); | 10612 instr = AddUncasted<HMod>(left, right); |
10605 break; | 10613 break; |
10606 } | 10614 } |
10607 case Token::DIV: | 10615 case Token::DIV: |
10608 instr = AddUncasted<HDiv>(left, right); | 10616 instr = AddUncasted<HDiv>(left, right); |
10609 break; | 10617 break; |
10610 case Token::BIT_XOR: | 10618 case Token::BIT_XOR: |
10611 case Token::BIT_AND: | 10619 case Token::BIT_AND: |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10965 Type* left_type, | 10973 Type* left_type, |
10966 Type* right_type, | 10974 Type* right_type, |
10967 Type* combined_type, | 10975 Type* combined_type, |
10968 HSourcePosition left_position, | 10976 HSourcePosition left_position, |
10969 HSourcePosition right_position, | 10977 HSourcePosition right_position, |
10970 PushBeforeSimulateBehavior push_sim_result, | 10978 PushBeforeSimulateBehavior push_sim_result, |
10971 BailoutId bailout_id) { | 10979 BailoutId bailout_id) { |
10972 // Cases handled below depend on collected type feedback. They should | 10980 // Cases handled below depend on collected type feedback. They should |
10973 // soft deoptimize when there is no type feedback. | 10981 // soft deoptimize when there is no type feedback. |
10974 if (!combined_type->IsInhabited()) { | 10982 if (!combined_type->IsInhabited()) { |
10975 Add<HDeoptimize>("Insufficient type feedback for combined type " | 10983 Add<HDeoptimize>( |
10976 "of binary operation", | 10984 Deoptimizer::kInsufficientTypeFeedbackForCombinedTypeOfBinaryOperation, |
10977 Deoptimizer::SOFT); | 10985 Deoptimizer::SOFT); |
10978 combined_type = left_type = right_type = Type::Any(zone()); | 10986 combined_type = left_type = right_type = Type::Any(zone()); |
10979 } | 10987 } |
10980 | 10988 |
10981 Representation left_rep = Representation::FromType(left_type); | 10989 Representation left_rep = Representation::FromType(left_type); |
10982 Representation right_rep = Representation::FromType(right_type); | 10990 Representation right_rep = Representation::FromType(right_type); |
10983 Representation combined_rep = Representation::FromType(combined_type); | 10991 Representation combined_rep = Representation::FromType(combined_type); |
10984 | 10992 |
10985 if (combined_type->Is(Type::Receiver())) { | 10993 if (combined_type->Is(Type::Receiver())) { |
10986 if (Token::IsEqualityOp(op)) { | 10994 if (Token::IsEqualityOp(op)) { |
10987 // HCompareObjectEqAndBranch can only deal with object, so | 10995 // HCompareObjectEqAndBranch can only deal with object, so |
10988 // exclude numbers. | 10996 // exclude numbers. |
10989 if ((left->IsConstant() && | 10997 if ((left->IsConstant() && |
10990 HConstant::cast(left)->HasNumberValue()) || | 10998 HConstant::cast(left)->HasNumberValue()) || |
10991 (right->IsConstant() && | 10999 (right->IsConstant() && |
10992 HConstant::cast(right)->HasNumberValue())) { | 11000 HConstant::cast(right)->HasNumberValue())) { |
10993 Add<HDeoptimize>("Type mismatch between feedback and constant", | 11001 Add<HDeoptimize>(Deoptimizer::kTypeMismatchBetweenFeedbackAndConstant, |
10994 Deoptimizer::SOFT); | 11002 Deoptimizer::SOFT); |
10995 // The caller expects a branch instruction, so make it happy. | 11003 // The caller expects a branch instruction, so make it happy. |
10996 return New<HBranch>(graph()->GetConstantTrue()); | 11004 return New<HBranch>(graph()->GetConstantTrue()); |
10997 } | 11005 } |
10998 // Can we get away with map check and not instance type check? | 11006 // Can we get away with map check and not instance type check? |
10999 HValue* operand_to_check = | 11007 HValue* operand_to_check = |
11000 left->block()->block_id() < right->block()->block_id() ? left : right; | 11008 left->block()->block_id() < right->block()->block_id() ? left : right; |
11001 if (combined_type->IsClass()) { | 11009 if (combined_type->IsClass()) { |
11002 Handle<Map> map = combined_type->AsClass()->Map(); | 11010 Handle<Map> map = combined_type->AsClass()->Map(); |
11003 AddCheckMap(operand_to_check, map); | 11011 AddCheckMap(operand_to_check, map); |
(...skipping 17 matching lines...) Expand all Loading... |
11021 return NULL; | 11029 return NULL; |
11022 } | 11030 } |
11023 } else if (combined_type->Is(Type::InternalizedString()) && | 11031 } else if (combined_type->Is(Type::InternalizedString()) && |
11024 Token::IsEqualityOp(op)) { | 11032 Token::IsEqualityOp(op)) { |
11025 // If we have a constant argument, it should be consistent with the type | 11033 // If we have a constant argument, it should be consistent with the type |
11026 // feedback (otherwise we fail assertions in HCompareObjectEqAndBranch). | 11034 // feedback (otherwise we fail assertions in HCompareObjectEqAndBranch). |
11027 if ((left->IsConstant() && | 11035 if ((left->IsConstant() && |
11028 !HConstant::cast(left)->HasInternalizedStringValue()) || | 11036 !HConstant::cast(left)->HasInternalizedStringValue()) || |
11029 (right->IsConstant() && | 11037 (right->IsConstant() && |
11030 !HConstant::cast(right)->HasInternalizedStringValue())) { | 11038 !HConstant::cast(right)->HasInternalizedStringValue())) { |
11031 Add<HDeoptimize>("Type mismatch between feedback and constant", | 11039 Add<HDeoptimize>(Deoptimizer::kTypeMismatchBetweenFeedbackAndConstant, |
11032 Deoptimizer::SOFT); | 11040 Deoptimizer::SOFT); |
11033 // The caller expects a branch instruction, so make it happy. | 11041 // The caller expects a branch instruction, so make it happy. |
11034 return New<HBranch>(graph()->GetConstantTrue()); | 11042 return New<HBranch>(graph()->GetConstantTrue()); |
11035 } | 11043 } |
11036 BuildCheckHeapObject(left); | 11044 BuildCheckHeapObject(left); |
11037 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING); | 11045 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING); |
11038 BuildCheckHeapObject(right); | 11046 BuildCheckHeapObject(right); |
11039 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING); | 11047 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING); |
11040 HCompareObjectEqAndBranch* result = | 11048 HCompareObjectEqAndBranch* result = |
11041 New<HCompareObjectEqAndBranch>(left, right); | 11049 New<HCompareObjectEqAndBranch>(left, right); |
(...skipping 2428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13470 if (ShouldProduceTraceOutput()) { | 13478 if (ShouldProduceTraceOutput()) { |
13471 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13479 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
13472 } | 13480 } |
13473 | 13481 |
13474 #ifdef DEBUG | 13482 #ifdef DEBUG |
13475 graph_->Verify(false); // No full verify. | 13483 graph_->Verify(false); // No full verify. |
13476 #endif | 13484 #endif |
13477 } | 13485 } |
13478 | 13486 |
13479 } } // namespace v8::internal | 13487 } } // namespace v8::internal |
OLD | NEW |