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 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6881 | 6884 |
6882 | 6885 |
6883 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric( | 6886 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric( |
6884 PropertyAccessType access_type, | 6887 PropertyAccessType access_type, |
6885 Expression* expr, | 6888 Expression* expr, |
6886 HValue* object, | 6889 HValue* object, |
6887 Handle<String> name, | 6890 Handle<String> name, |
6888 HValue* value, | 6891 HValue* value, |
6889 bool is_uninitialized) { | 6892 bool is_uninitialized) { |
6890 if (is_uninitialized) { | 6893 if (is_uninitialized) { |
6891 Add<HDeoptimize>("Insufficient type feedback for generic named access", | 6894 Add<HDeoptimize>( |
6892 Deoptimizer::SOFT); | 6895 Deoptimizer::kInsufficientTypeFeedbackForGenericNamedAccess, |
| 6896 Deoptimizer::SOFT); |
6893 } | 6897 } |
6894 if (access_type == LOAD) { | 6898 if (access_type == LOAD) { |
6895 HLoadNamedGeneric* result = New<HLoadNamedGeneric>(object, name); | 6899 HLoadNamedGeneric* result = New<HLoadNamedGeneric>(object, name); |
6896 if (FLAG_vector_ics) { | 6900 if (FLAG_vector_ics) { |
6897 Handle<SharedFunctionInfo> current_shared = | 6901 Handle<SharedFunctionInfo> current_shared = |
6898 function_state()->compilation_info()->shared_info(); | 6902 function_state()->compilation_info()->shared_info(); |
6899 Handle<TypeFeedbackVector> vector = | 6903 Handle<TypeFeedbackVector> vector = |
6900 handle(current_shared->feedback_vector(), isolate()); | 6904 handle(current_shared->feedback_vector(), isolate()); |
6901 FeedbackVectorICSlot slot = expr->AsProperty()->PropertyFeedbackSlot(); | 6905 FeedbackVectorICSlot slot = expr->AsProperty()->PropertyFeedbackSlot(); |
6902 result->SetVectorAndSlot(vector, slot); | 6906 result->SetVectorAndSlot(vector, slot); |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7184 set_current_block(other_map); | 7188 set_current_block(other_map); |
7185 } | 7189 } |
7186 | 7190 |
7187 // Ensure that we visited at least one map above that goes to join. This is | 7191 // Ensure that we visited at least one map above that goes to join. This is |
7188 // necessary because FinishExitWithHardDeoptimization does an AbnormalExit | 7192 // necessary because FinishExitWithHardDeoptimization does an AbnormalExit |
7189 // rather than joining the join block. If this becomes an issue, insert a | 7193 // rather than joining the join block. If this becomes an issue, insert a |
7190 // generic access in the case length() == 0. | 7194 // generic access in the case length() == 0. |
7191 DCHECK(join->predecessors()->length() > 0); | 7195 DCHECK(join->predecessors()->length() > 0); |
7192 // Deopt if none of the cases matched. | 7196 // Deopt if none of the cases matched. |
7193 NoObservableSideEffectsScope scope(this); | 7197 NoObservableSideEffectsScope scope(this); |
7194 FinishExitWithHardDeoptimization("Unknown map in polymorphic element access"); | 7198 FinishExitWithHardDeoptimization( |
| 7199 Deoptimizer::kUnknownMapInPolymorphicElementAccess); |
7195 set_current_block(join); | 7200 set_current_block(join); |
7196 return access_type == STORE ? val : Pop(); | 7201 return access_type == STORE ? val : Pop(); |
7197 } | 7202 } |
7198 | 7203 |
7199 | 7204 |
7200 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( | 7205 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( |
7201 HValue* obj, HValue* key, HValue* val, Expression* expr, BailoutId ast_id, | 7206 HValue* obj, HValue* key, HValue* val, Expression* expr, BailoutId ast_id, |
7202 BailoutId return_id, PropertyAccessType access_type, | 7207 BailoutId return_id, PropertyAccessType access_type, |
7203 bool* has_side_effects) { | 7208 bool* has_side_effects) { |
7204 // TODO(mvstanton): This optimization causes trouble for vector-based | 7209 // TODO(mvstanton): This optimization causes trouble for vector-based |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7279 obj, key, val, NULL, map, access_type, expr->GetStoreMode()); | 7284 obj, key, val, NULL, map, access_type, expr->GetStoreMode()); |
7280 } | 7285 } |
7281 } else if (!force_generic && (types != NULL && !types->is_empty())) { | 7286 } else if (!force_generic && (types != NULL && !types->is_empty())) { |
7282 return HandlePolymorphicElementAccess( | 7287 return HandlePolymorphicElementAccess( |
7283 expr, obj, key, val, types, access_type, | 7288 expr, obj, key, val, types, access_type, |
7284 expr->GetStoreMode(), has_side_effects); | 7289 expr->GetStoreMode(), has_side_effects); |
7285 } else { | 7290 } else { |
7286 if (access_type == STORE) { | 7291 if (access_type == STORE) { |
7287 if (expr->IsAssignment() && | 7292 if (expr->IsAssignment() && |
7288 expr->AsAssignment()->HasNoTypeInformation()) { | 7293 expr->AsAssignment()->HasNoTypeInformation()) { |
7289 Add<HDeoptimize>("Insufficient type feedback for keyed store", | 7294 Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedStore, |
7290 Deoptimizer::SOFT); | 7295 Deoptimizer::SOFT); |
7291 } | 7296 } |
7292 } else { | 7297 } else { |
7293 if (expr->AsProperty()->HasNoTypeInformation()) { | 7298 if (expr->AsProperty()->HasNoTypeInformation()) { |
7294 Add<HDeoptimize>("Insufficient type feedback for keyed load", | 7299 Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedLoad, |
7295 Deoptimizer::SOFT); | 7300 Deoptimizer::SOFT); |
7296 } | 7301 } |
7297 } | 7302 } |
7298 instr = AddInstruction(BuildKeyedGeneric(access_type, expr, obj, key, val)); | 7303 instr = AddInstruction(BuildKeyedGeneric(access_type, expr, obj, key, val)); |
7299 } | 7304 } |
7300 *has_side_effects = instr->HasObservableSideEffects(); | 7305 *has_side_effects = instr->HasObservableSideEffects(); |
7301 return instr; | 7306 return instr; |
7302 } | 7307 } |
7303 | 7308 |
7304 | 7309 |
(...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7729 } | 7734 } |
7730 | 7735 |
7731 if (current_block() != NULL) Goto(join); | 7736 if (current_block() != NULL) Goto(join); |
7732 set_current_block(if_false); | 7737 set_current_block(if_false); |
7733 } | 7738 } |
7734 | 7739 |
7735 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 7740 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
7736 // know about and do not want to handle ones we've never seen. Otherwise | 7741 // know about and do not want to handle ones we've never seen. Otherwise |
7737 // use a generic IC. | 7742 // use a generic IC. |
7738 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { | 7743 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { |
7739 FinishExitWithHardDeoptimization("Unknown map in polymorphic call"); | 7744 FinishExitWithHardDeoptimization(Deoptimizer::kUnknownMapInPolymorphicCall); |
7740 } else { | 7745 } else { |
7741 Property* prop = expr->expression()->AsProperty(); | 7746 Property* prop = expr->expression()->AsProperty(); |
7742 HInstruction* function = BuildNamedGeneric( | 7747 HInstruction* function = BuildNamedGeneric( |
7743 LOAD, prop, receiver, name, NULL, prop->IsUninitialized()); | 7748 LOAD, prop, receiver, name, NULL, prop->IsUninitialized()); |
7744 AddInstruction(function); | 7749 AddInstruction(function); |
7745 Push(function); | 7750 Push(function); |
7746 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 7751 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); |
7747 | 7752 |
7748 environment()->SetExpressionStackAt(1, function); | 7753 environment()->SetExpressionStackAt(1, function); |
7749 environment()->SetExpressionStackAt(0, receiver); | 7754 environment()->SetExpressionStackAt(0, receiver); |
(...skipping 1486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9236 return; | 9241 return; |
9237 } else { | 9242 } else { |
9238 call = BuildCallConstantFunction(known_function, argument_count); | 9243 call = BuildCallConstantFunction(known_function, argument_count); |
9239 } | 9244 } |
9240 | 9245 |
9241 } else { | 9246 } else { |
9242 ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED; | 9247 ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED; |
9243 if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) { | 9248 if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) { |
9244 // We have to use EAGER deoptimization here because Deoptimizer::SOFT | 9249 // We have to use EAGER deoptimization here because Deoptimizer::SOFT |
9245 // gets ignored by the always-opt flag, which leads to incorrect code. | 9250 // gets ignored by the always-opt flag, which leads to incorrect code. |
9246 Add<HDeoptimize>("Insufficient type feedback for call with arguments", | 9251 Add<HDeoptimize>( |
9247 Deoptimizer::EAGER); | 9252 Deoptimizer::kInsufficientTypeFeedbackForCallWithArguments, |
| 9253 Deoptimizer::EAGER); |
9248 arguments_flag = ARGUMENTS_FAKED; | 9254 arguments_flag = ARGUMENTS_FAKED; |
9249 } | 9255 } |
9250 | 9256 |
9251 // Push the function under the receiver. | 9257 // Push the function under the receiver. |
9252 environment()->SetExpressionStackAt(0, function); | 9258 environment()->SetExpressionStackAt(0, function); |
9253 Push(receiver); | 9259 Push(receiver); |
9254 | 9260 |
9255 CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag)); | 9261 CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag)); |
9256 CallFunctionFlags flags = receiver->type().IsJSObject() | 9262 CallFunctionFlags flags = receiver->type().IsJSObject() |
9257 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD; | 9263 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD; |
(...skipping 1210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10468 Representation left_rep = Representation::FromType(left_type); | 10474 Representation left_rep = Representation::FromType(left_type); |
10469 Representation right_rep = Representation::FromType(right_type); | 10475 Representation right_rep = Representation::FromType(right_type); |
10470 | 10476 |
10471 bool maybe_string_add = op == Token::ADD && | 10477 bool maybe_string_add = op == Token::ADD && |
10472 (left_type->Maybe(Type::String()) || | 10478 (left_type->Maybe(Type::String()) || |
10473 left_type->Maybe(Type::Receiver()) || | 10479 left_type->Maybe(Type::Receiver()) || |
10474 right_type->Maybe(Type::String()) || | 10480 right_type->Maybe(Type::String()) || |
10475 right_type->Maybe(Type::Receiver())); | 10481 right_type->Maybe(Type::Receiver())); |
10476 | 10482 |
10477 if (!left_type->IsInhabited()) { | 10483 if (!left_type->IsInhabited()) { |
10478 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", | 10484 Add<HDeoptimize>( |
10479 Deoptimizer::SOFT); | 10485 Deoptimizer::kInsufficientTypeFeedbackForLHSOfBinaryOperation, |
| 10486 Deoptimizer::SOFT); |
10480 // TODO(rossberg): we should be able to get rid of non-continuous | 10487 // TODO(rossberg): we should be able to get rid of non-continuous |
10481 // defaults. | 10488 // defaults. |
10482 left_type = Type::Any(zone()); | 10489 left_type = Type::Any(zone()); |
10483 } else { | 10490 } else { |
10484 if (!maybe_string_add) left = TruncateToNumber(left, &left_type); | 10491 if (!maybe_string_add) left = TruncateToNumber(left, &left_type); |
10485 left_rep = Representation::FromType(left_type); | 10492 left_rep = Representation::FromType(left_type); |
10486 } | 10493 } |
10487 | 10494 |
10488 if (!right_type->IsInhabited()) { | 10495 if (!right_type->IsInhabited()) { |
10489 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", | 10496 Add<HDeoptimize>( |
10490 Deoptimizer::SOFT); | 10497 Deoptimizer::kInsufficientTypeFeedbackForRHSOfBinaryOperation, |
| 10498 Deoptimizer::SOFT); |
10491 right_type = Type::Any(zone()); | 10499 right_type = Type::Any(zone()); |
10492 } else { | 10500 } else { |
10493 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); | 10501 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); |
10494 right_rep = Representation::FromType(right_type); | 10502 right_rep = Representation::FromType(right_type); |
10495 } | 10503 } |
10496 | 10504 |
10497 // Special case for string addition here. | 10505 // Special case for string addition here. |
10498 if (op == Token::ADD && | 10506 if (op == Token::ADD && |
10499 (left_type->Is(Type::String()) || right_type->Is(Type::String()))) { | 10507 (left_type->Is(Type::String()) || right_type->Is(Type::String()))) { |
10500 // Validate type feedback for left argument. | 10508 // Validate type feedback for left argument. |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10600 instr = AddUncasted<HMul>(left, right); | 10608 instr = AddUncasted<HMul>(left, right); |
10601 break; | 10609 break; |
10602 case Token::MOD: { | 10610 case Token::MOD: { |
10603 if (fixed_right_arg.has_value && | 10611 if (fixed_right_arg.has_value && |
10604 !right->EqualsInteger32Constant(fixed_right_arg.value)) { | 10612 !right->EqualsInteger32Constant(fixed_right_arg.value)) { |
10605 HConstant* fixed_right = Add<HConstant>( | 10613 HConstant* fixed_right = Add<HConstant>( |
10606 static_cast<int>(fixed_right_arg.value)); | 10614 static_cast<int>(fixed_right_arg.value)); |
10607 IfBuilder if_same(this); | 10615 IfBuilder if_same(this); |
10608 if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ); | 10616 if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ); |
10609 if_same.Then(); | 10617 if_same.Then(); |
10610 if_same.ElseDeopt("Unexpected RHS of binary operation"); | 10618 if_same.ElseDeopt(Deoptimizer::kUnexpectedRHSOfBinaryOperation); |
10611 right = fixed_right; | 10619 right = fixed_right; |
10612 } | 10620 } |
10613 instr = AddUncasted<HMod>(left, right); | 10621 instr = AddUncasted<HMod>(left, right); |
10614 break; | 10622 break; |
10615 } | 10623 } |
10616 case Token::DIV: | 10624 case Token::DIV: |
10617 instr = AddUncasted<HDiv>(left, right); | 10625 instr = AddUncasted<HDiv>(left, right); |
10618 break; | 10626 break; |
10619 case Token::BIT_XOR: | 10627 case Token::BIT_XOR: |
10620 case Token::BIT_AND: | 10628 case Token::BIT_AND: |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10974 Type* left_type, | 10982 Type* left_type, |
10975 Type* right_type, | 10983 Type* right_type, |
10976 Type* combined_type, | 10984 Type* combined_type, |
10977 HSourcePosition left_position, | 10985 HSourcePosition left_position, |
10978 HSourcePosition right_position, | 10986 HSourcePosition right_position, |
10979 PushBeforeSimulateBehavior push_sim_result, | 10987 PushBeforeSimulateBehavior push_sim_result, |
10980 BailoutId bailout_id) { | 10988 BailoutId bailout_id) { |
10981 // Cases handled below depend on collected type feedback. They should | 10989 // Cases handled below depend on collected type feedback. They should |
10982 // soft deoptimize when there is no type feedback. | 10990 // soft deoptimize when there is no type feedback. |
10983 if (!combined_type->IsInhabited()) { | 10991 if (!combined_type->IsInhabited()) { |
10984 Add<HDeoptimize>("Insufficient type feedback for combined type " | 10992 Add<HDeoptimize>( |
10985 "of binary operation", | 10993 Deoptimizer::kInsufficientTypeFeedbackForCombinedTypeOfBinaryOperation, |
10986 Deoptimizer::SOFT); | 10994 Deoptimizer::SOFT); |
10987 combined_type = left_type = right_type = Type::Any(zone()); | 10995 combined_type = left_type = right_type = Type::Any(zone()); |
10988 } | 10996 } |
10989 | 10997 |
10990 Representation left_rep = Representation::FromType(left_type); | 10998 Representation left_rep = Representation::FromType(left_type); |
10991 Representation right_rep = Representation::FromType(right_type); | 10999 Representation right_rep = Representation::FromType(right_type); |
10992 Representation combined_rep = Representation::FromType(combined_type); | 11000 Representation combined_rep = Representation::FromType(combined_type); |
10993 | 11001 |
10994 if (combined_type->Is(Type::Receiver())) { | 11002 if (combined_type->Is(Type::Receiver())) { |
10995 if (Token::IsEqualityOp(op)) { | 11003 if (Token::IsEqualityOp(op)) { |
10996 // HCompareObjectEqAndBranch can only deal with object, so | 11004 // HCompareObjectEqAndBranch can only deal with object, so |
10997 // exclude numbers. | 11005 // exclude numbers. |
10998 if ((left->IsConstant() && | 11006 if ((left->IsConstant() && |
10999 HConstant::cast(left)->HasNumberValue()) || | 11007 HConstant::cast(left)->HasNumberValue()) || |
11000 (right->IsConstant() && | 11008 (right->IsConstant() && |
11001 HConstant::cast(right)->HasNumberValue())) { | 11009 HConstant::cast(right)->HasNumberValue())) { |
11002 Add<HDeoptimize>("Type mismatch between feedback and constant", | 11010 Add<HDeoptimize>(Deoptimizer::kTypeMismatchBetweenFeedbackAndConstant, |
11003 Deoptimizer::SOFT); | 11011 Deoptimizer::SOFT); |
11004 // The caller expects a branch instruction, so make it happy. | 11012 // The caller expects a branch instruction, so make it happy. |
11005 return New<HBranch>(graph()->GetConstantTrue()); | 11013 return New<HBranch>(graph()->GetConstantTrue()); |
11006 } | 11014 } |
11007 // Can we get away with map check and not instance type check? | 11015 // Can we get away with map check and not instance type check? |
11008 HValue* operand_to_check = | 11016 HValue* operand_to_check = |
11009 left->block()->block_id() < right->block()->block_id() ? left : right; | 11017 left->block()->block_id() < right->block()->block_id() ? left : right; |
11010 if (combined_type->IsClass()) { | 11018 if (combined_type->IsClass()) { |
11011 Handle<Map> map = combined_type->AsClass()->Map(); | 11019 Handle<Map> map = combined_type->AsClass()->Map(); |
11012 AddCheckMap(operand_to_check, map); | 11020 AddCheckMap(operand_to_check, map); |
(...skipping 17 matching lines...) Expand all Loading... |
11030 return NULL; | 11038 return NULL; |
11031 } | 11039 } |
11032 } else if (combined_type->Is(Type::InternalizedString()) && | 11040 } else if (combined_type->Is(Type::InternalizedString()) && |
11033 Token::IsEqualityOp(op)) { | 11041 Token::IsEqualityOp(op)) { |
11034 // If we have a constant argument, it should be consistent with the type | 11042 // If we have a constant argument, it should be consistent with the type |
11035 // feedback (otherwise we fail assertions in HCompareObjectEqAndBranch). | 11043 // feedback (otherwise we fail assertions in HCompareObjectEqAndBranch). |
11036 if ((left->IsConstant() && | 11044 if ((left->IsConstant() && |
11037 !HConstant::cast(left)->HasInternalizedStringValue()) || | 11045 !HConstant::cast(left)->HasInternalizedStringValue()) || |
11038 (right->IsConstant() && | 11046 (right->IsConstant() && |
11039 !HConstant::cast(right)->HasInternalizedStringValue())) { | 11047 !HConstant::cast(right)->HasInternalizedStringValue())) { |
11040 Add<HDeoptimize>("Type mismatch between feedback and constant", | 11048 Add<HDeoptimize>(Deoptimizer::kTypeMismatchBetweenFeedbackAndConstant, |
11041 Deoptimizer::SOFT); | 11049 Deoptimizer::SOFT); |
11042 // The caller expects a branch instruction, so make it happy. | 11050 // The caller expects a branch instruction, so make it happy. |
11043 return New<HBranch>(graph()->GetConstantTrue()); | 11051 return New<HBranch>(graph()->GetConstantTrue()); |
11044 } | 11052 } |
11045 BuildCheckHeapObject(left); | 11053 BuildCheckHeapObject(left); |
11046 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING); | 11054 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING); |
11047 BuildCheckHeapObject(right); | 11055 BuildCheckHeapObject(right); |
11048 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING); | 11056 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING); |
11049 HCompareObjectEqAndBranch* result = | 11057 HCompareObjectEqAndBranch* result = |
11050 New<HCompareObjectEqAndBranch>(left, right); | 11058 New<HCompareObjectEqAndBranch>(left, right); |
(...skipping 2429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13480 if (ShouldProduceTraceOutput()) { | 13488 if (ShouldProduceTraceOutput()) { |
13481 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13489 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
13482 } | 13490 } |
13483 | 13491 |
13484 #ifdef DEBUG | 13492 #ifdef DEBUG |
13485 graph_->Verify(false); // No full verify. | 13493 graph_->Verify(false); // No full verify. |
13486 #endif | 13494 #endif |
13487 } | 13495 } |
13488 | 13496 |
13489 } } // namespace v8::internal | 13497 } } // namespace v8::internal |
OLD | NEW |