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

Side by Side Diff: src/hydrogen.cc

Issue 874323003: Externalize deoptimization reasons. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698