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

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

Powered by Google App Engine
This is Rietveld 408576698