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