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

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

Powered by Google App Engine
This is Rietveld 408576698