OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/hydrogen.h" | 5 #include "src/hydrogen.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "src/v8.h" | 9 #include "src/v8.h" |
10 | 10 |
(...skipping 5291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5302 return ast_context()->ReturnInstruction(instr, expr->id()); | 5302 return ast_context()->ReturnInstruction(instr, expr->id()); |
5303 } | 5303 } |
5304 } else { | 5304 } else { |
5305 HValue* global_object = Add<HLoadNamedField>( | 5305 HValue* global_object = Add<HLoadNamedField>( |
5306 context(), static_cast<HValue*>(NULL), | 5306 context(), static_cast<HValue*>(NULL), |
5307 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); | 5307 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); |
5308 HLoadGlobalGeneric* instr = | 5308 HLoadGlobalGeneric* instr = |
5309 New<HLoadGlobalGeneric>(global_object, | 5309 New<HLoadGlobalGeneric>(global_object, |
5310 variable->name(), | 5310 variable->name(), |
5311 ast_context()->is_for_typeof()); | 5311 ast_context()->is_for_typeof()); |
| 5312 if (FLAG_vector_ics) { |
| 5313 instr->set_slot(expr->VariableFeedbackSlot()); |
| 5314 } |
5312 return ast_context()->ReturnInstruction(instr, expr->id()); | 5315 return ast_context()->ReturnInstruction(instr, expr->id()); |
5313 } | 5316 } |
5314 } | 5317 } |
5315 | 5318 |
5316 case Variable::PARAMETER: | 5319 case Variable::PARAMETER: |
5317 case Variable::LOCAL: { | 5320 case Variable::LOCAL: { |
5318 HValue* value = LookupAndMakeLive(variable); | 5321 HValue* value = LookupAndMakeLive(variable); |
5319 if (value == graph()->GetConstantHole()) { | 5322 if (value == graph()->GetConstantHole()) { |
5320 ASSERT(IsDeclaredVariableMode(variable->mode()) && | 5323 ASSERT(IsDeclaredVariableMode(variable->mode()) && |
5321 variable->mode() != VAR); | 5324 variable->mode() != VAR); |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5520 if (key->value()->IsInternalizedString()) { | 5523 if (key->value()->IsInternalizedString()) { |
5521 if (property->emit_store()) { | 5524 if (property->emit_store()) { |
5522 CHECK_ALIVE(VisitForValue(value)); | 5525 CHECK_ALIVE(VisitForValue(value)); |
5523 HValue* value = Pop(); | 5526 HValue* value = Pop(); |
5524 Handle<Map> map = property->GetReceiverType(); | 5527 Handle<Map> map = property->GetReceiverType(); |
5525 Handle<String> name = property->key()->AsPropertyName(); | 5528 Handle<String> name = property->key()->AsPropertyName(); |
5526 HInstruction* store; | 5529 HInstruction* store; |
5527 if (map.is_null()) { | 5530 if (map.is_null()) { |
5528 // If we don't know the monomorphic type, do a generic store. | 5531 // If we don't know the monomorphic type, do a generic store. |
5529 CHECK_ALIVE(store = BuildNamedGeneric( | 5532 CHECK_ALIVE(store = BuildNamedGeneric( |
5530 STORE, literal, name, value)); | 5533 STORE, NULL, literal, name, value)); |
5531 } else { | 5534 } else { |
5532 PropertyAccessInfo info(this, STORE, ToType(map), name); | 5535 PropertyAccessInfo info(this, STORE, ToType(map), name); |
5533 if (info.CanAccessMonomorphic()) { | 5536 if (info.CanAccessMonomorphic()) { |
5534 HValue* checked_literal = Add<HCheckMaps>(literal, map); | 5537 HValue* checked_literal = Add<HCheckMaps>(literal, map); |
5535 ASSERT(!info.lookup()->IsPropertyCallbacks()); | 5538 ASSERT(!info.lookup()->IsPropertyCallbacks()); |
5536 store = BuildMonomorphicAccess( | 5539 store = BuildMonomorphicAccess( |
5537 &info, literal, checked_literal, value, | 5540 &info, literal, checked_literal, value, |
5538 BailoutId::None(), BailoutId::None()); | 5541 BailoutId::None(), BailoutId::None()); |
5539 } else { | 5542 } else { |
5540 CHECK_ALIVE(store = BuildNamedGeneric( | 5543 CHECK_ALIVE(store = BuildNamedGeneric( |
5541 STORE, literal, name, value)); | 5544 STORE, NULL, literal, name, value)); |
5542 } | 5545 } |
5543 } | 5546 } |
5544 AddInstruction(store); | 5547 AddInstruction(store); |
5545 if (store->HasObservableSideEffects()) { | 5548 if (store->HasObservableSideEffects()) { |
5546 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE); | 5549 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE); |
5547 } | 5550 } |
5548 } else { | 5551 } else { |
5549 CHECK_ALIVE(VisitForEffect(value)); | 5552 CHECK_ALIVE(VisitForEffect(value)); |
5550 } | 5553 } |
5551 break; | 5554 break; |
(...skipping 584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6136 if (info->IsLoad()) { | 6139 if (info->IsLoad()) { |
6137 return New<HConstant>(info->constant()); | 6140 return New<HConstant>(info->constant()); |
6138 } else { | 6141 } else { |
6139 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); | 6142 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); |
6140 } | 6143 } |
6141 } | 6144 } |
6142 | 6145 |
6143 | 6146 |
6144 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess( | 6147 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess( |
6145 PropertyAccessType access_type, | 6148 PropertyAccessType access_type, |
| 6149 Expression* expr, |
6146 BailoutId ast_id, | 6150 BailoutId ast_id, |
6147 BailoutId return_id, | 6151 BailoutId return_id, |
6148 HValue* object, | 6152 HValue* object, |
6149 HValue* value, | 6153 HValue* value, |
6150 SmallMapList* types, | 6154 SmallMapList* types, |
6151 Handle<String> name) { | 6155 Handle<String> name) { |
6152 // Something did not match; must use a polymorphic load. | 6156 // Something did not match; must use a polymorphic load. |
6153 int count = 0; | 6157 int count = 0; |
6154 HBasicBlock* join = NULL; | 6158 HBasicBlock* join = NULL; |
6155 HBasicBlock* number_block = NULL; | 6159 HBasicBlock* number_block = NULL; |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6249 if (current_block() != NULL) Goto(join); | 6253 if (current_block() != NULL) Goto(join); |
6250 set_current_block(if_false); | 6254 set_current_block(if_false); |
6251 } | 6255 } |
6252 | 6256 |
6253 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 6257 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
6254 // know about and do not want to handle ones we've never seen. Otherwise | 6258 // know about and do not want to handle ones we've never seen. Otherwise |
6255 // use a generic IC. | 6259 // use a generic IC. |
6256 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | 6260 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { |
6257 FinishExitWithHardDeoptimization("Uknown map in polymorphic access"); | 6261 FinishExitWithHardDeoptimization("Uknown map in polymorphic access"); |
6258 } else { | 6262 } else { |
6259 HInstruction* instr = BuildNamedGeneric(access_type, object, name, value); | 6263 HInstruction* instr = BuildNamedGeneric(access_type, expr, object, name, |
| 6264 value); |
6260 AddInstruction(instr); | 6265 AddInstruction(instr); |
6261 if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value); | 6266 if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value); |
6262 | 6267 |
6263 if (join != NULL) { | 6268 if (join != NULL) { |
6264 Goto(join); | 6269 Goto(join); |
6265 } else { | 6270 } else { |
6266 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6271 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
6267 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 6272 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
6268 return; | 6273 return; |
6269 } | 6274 } |
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6696 return Add<HConstant>(c_string->StringValue()->length()); | 6701 return Add<HConstant>(c_string->StringValue()->length()); |
6697 } | 6702 } |
6698 } | 6703 } |
6699 return Add<HLoadNamedField>(string, static_cast<HValue*>(NULL), | 6704 return Add<HLoadNamedField>(string, static_cast<HValue*>(NULL), |
6700 HObjectAccess::ForStringLength()); | 6705 HObjectAccess::ForStringLength()); |
6701 } | 6706 } |
6702 | 6707 |
6703 | 6708 |
6704 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric( | 6709 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric( |
6705 PropertyAccessType access_type, | 6710 PropertyAccessType access_type, |
| 6711 Expression* expr, |
6706 HValue* object, | 6712 HValue* object, |
6707 Handle<String> name, | 6713 Handle<String> name, |
6708 HValue* value, | 6714 HValue* value, |
6709 bool is_uninitialized) { | 6715 bool is_uninitialized) { |
6710 if (is_uninitialized) { | 6716 if (is_uninitialized) { |
6711 Add<HDeoptimize>("Insufficient type feedback for generic named access", | 6717 Add<HDeoptimize>("Insufficient type feedback for generic named access", |
6712 Deoptimizer::SOFT); | 6718 Deoptimizer::SOFT); |
6713 } | 6719 } |
6714 if (access_type == LOAD) { | 6720 if (access_type == LOAD) { |
6715 return New<HLoadNamedGeneric>(object, name); | 6721 HLoadNamedGeneric* result = New<HLoadNamedGeneric>(object, name); |
| 6722 if (FLAG_vector_ics) { |
| 6723 result->set_slot(expr->AsProperty()->PropertyFeedbackSlot()); |
| 6724 } |
| 6725 return result; |
6716 } else { | 6726 } else { |
6717 return New<HStoreNamedGeneric>(object, name, value, function_strict_mode()); | 6727 return New<HStoreNamedGeneric>(object, name, value, function_strict_mode()); |
6718 } | 6728 } |
6719 } | 6729 } |
6720 | 6730 |
6721 | 6731 |
6722 | 6732 |
6723 HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric( | 6733 HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric( |
6724 PropertyAccessType access_type, | 6734 PropertyAccessType access_type, |
| 6735 Expression* expr, |
6725 HValue* object, | 6736 HValue* object, |
6726 HValue* key, | 6737 HValue* key, |
6727 HValue* value) { | 6738 HValue* value) { |
6728 if (access_type == LOAD) { | 6739 if (access_type == LOAD) { |
6729 return New<HLoadKeyedGeneric>(object, key); | 6740 HLoadKeyedGeneric* result = New<HLoadKeyedGeneric>(object, key); |
| 6741 if (FLAG_vector_ics) { |
| 6742 result->set_slot(expr->AsProperty()->PropertyFeedbackSlot()); |
| 6743 } |
| 6744 return result; |
6730 } else { | 6745 } else { |
6731 return New<HStoreKeyedGeneric>(object, key, value, function_strict_mode()); | 6746 return New<HStoreKeyedGeneric>(object, key, value, function_strict_mode()); |
6732 } | 6747 } |
6733 } | 6748 } |
6734 | 6749 |
6735 | 6750 |
6736 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) { | 6751 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) { |
6737 // Loads from a "stock" fast holey double arrays can elide the hole check. | 6752 // Loads from a "stock" fast holey double arrays can elide the hole check. |
6738 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; | 6753 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; |
6739 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && | 6754 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6845 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( | 6860 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( |
6846 checked_object, key, val, | 6861 checked_object, key, val, |
6847 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, | 6862 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, |
6848 consolidated_elements_kind, | 6863 consolidated_elements_kind, |
6849 LOAD, NEVER_RETURN_HOLE, STANDARD_STORE); | 6864 LOAD, NEVER_RETURN_HOLE, STANDARD_STORE); |
6850 return instr; | 6865 return instr; |
6851 } | 6866 } |
6852 | 6867 |
6853 | 6868 |
6854 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( | 6869 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( |
| 6870 Expression* expr, |
6855 HValue* object, | 6871 HValue* object, |
6856 HValue* key, | 6872 HValue* key, |
6857 HValue* val, | 6873 HValue* val, |
6858 SmallMapList* maps, | 6874 SmallMapList* maps, |
6859 PropertyAccessType access_type, | 6875 PropertyAccessType access_type, |
6860 KeyedAccessStoreMode store_mode, | 6876 KeyedAccessStoreMode store_mode, |
6861 bool* has_side_effects) { | 6877 bool* has_side_effects) { |
6862 *has_side_effects = false; | 6878 *has_side_effects = false; |
6863 BuildCheckHeapObject(object); | 6879 BuildCheckHeapObject(object); |
6864 | 6880 |
(...skipping 11 matching lines...) Expand all Loading... |
6876 // Collect possible transition targets. | 6892 // Collect possible transition targets. |
6877 MapHandleList possible_transitioned_maps(maps->length()); | 6893 MapHandleList possible_transitioned_maps(maps->length()); |
6878 for (int i = 0; i < maps->length(); ++i) { | 6894 for (int i = 0; i < maps->length(); ++i) { |
6879 Handle<Map> map = maps->at(i); | 6895 Handle<Map> map = maps->at(i); |
6880 ElementsKind elements_kind = map->elements_kind(); | 6896 ElementsKind elements_kind = map->elements_kind(); |
6881 if (IsFastElementsKind(elements_kind) && | 6897 if (IsFastElementsKind(elements_kind) && |
6882 elements_kind != GetInitialFastElementsKind()) { | 6898 elements_kind != GetInitialFastElementsKind()) { |
6883 possible_transitioned_maps.Add(map); | 6899 possible_transitioned_maps.Add(map); |
6884 } | 6900 } |
6885 if (elements_kind == SLOPPY_ARGUMENTS_ELEMENTS) { | 6901 if (elements_kind == SLOPPY_ARGUMENTS_ELEMENTS) { |
6886 HInstruction* result = BuildKeyedGeneric(access_type, object, key, val); | 6902 HInstruction* result = BuildKeyedGeneric(access_type, expr, object, key, |
| 6903 val); |
6887 *has_side_effects = result->HasObservableSideEffects(); | 6904 *has_side_effects = result->HasObservableSideEffects(); |
6888 return AddInstruction(result); | 6905 return AddInstruction(result); |
6889 } | 6906 } |
6890 } | 6907 } |
6891 // Get transition target for each map (NULL == no transition). | 6908 // Get transition target for each map (NULL == no transition). |
6892 for (int i = 0; i < maps->length(); ++i) { | 6909 for (int i = 0; i < maps->length(); ++i) { |
6893 Handle<Map> map = maps->at(i); | 6910 Handle<Map> map = maps->at(i); |
6894 Handle<Map> transitioned_map = | 6911 Handle<Map> transitioned_map = |
6895 map->FindTransitionedMap(&possible_transitioned_maps); | 6912 map->FindTransitionedMap(&possible_transitioned_maps); |
6896 transition_target.Add(transitioned_map); | 6913 transition_target.Add(transitioned_map); |
(...skipping 16 matching lines...) Expand all Loading... |
6913 } | 6930 } |
6914 | 6931 |
6915 // If only one map is left after transitioning, handle this case | 6932 // If only one map is left after transitioning, handle this case |
6916 // monomorphically. | 6933 // monomorphically. |
6917 ASSERT(untransitionable_maps.length() >= 1); | 6934 ASSERT(untransitionable_maps.length() >= 1); |
6918 if (untransitionable_maps.length() == 1) { | 6935 if (untransitionable_maps.length() == 1) { |
6919 Handle<Map> untransitionable_map = untransitionable_maps[0]; | 6936 Handle<Map> untransitionable_map = untransitionable_maps[0]; |
6920 HInstruction* instr = NULL; | 6937 HInstruction* instr = NULL; |
6921 if (untransitionable_map->has_slow_elements_kind() || | 6938 if (untransitionable_map->has_slow_elements_kind() || |
6922 !untransitionable_map->IsJSObjectMap()) { | 6939 !untransitionable_map->IsJSObjectMap()) { |
6923 instr = AddInstruction(BuildKeyedGeneric(access_type, object, key, val)); | 6940 instr = AddInstruction(BuildKeyedGeneric(access_type, expr, object, key, |
| 6941 val)); |
6924 } else { | 6942 } else { |
6925 instr = BuildMonomorphicElementAccess( | 6943 instr = BuildMonomorphicElementAccess( |
6926 object, key, val, transition, untransitionable_map, access_type, | 6944 object, key, val, transition, untransitionable_map, access_type, |
6927 store_mode); | 6945 store_mode); |
6928 } | 6946 } |
6929 *has_side_effects |= instr->HasObservableSideEffects(); | 6947 *has_side_effects |= instr->HasObservableSideEffects(); |
6930 return access_type == STORE ? NULL : instr; | 6948 return access_type == STORE ? NULL : instr; |
6931 } | 6949 } |
6932 | 6950 |
6933 HBasicBlock* join = graph()->CreateBasicBlock(); | 6951 HBasicBlock* join = graph()->CreateBasicBlock(); |
6934 | 6952 |
6935 for (int i = 0; i < untransitionable_maps.length(); ++i) { | 6953 for (int i = 0; i < untransitionable_maps.length(); ++i) { |
6936 Handle<Map> map = untransitionable_maps[i]; | 6954 Handle<Map> map = untransitionable_maps[i]; |
6937 if (!map->IsJSObjectMap()) continue; | 6955 if (!map->IsJSObjectMap()) continue; |
6938 ElementsKind elements_kind = map->elements_kind(); | 6956 ElementsKind elements_kind = map->elements_kind(); |
6939 HBasicBlock* this_map = graph()->CreateBasicBlock(); | 6957 HBasicBlock* this_map = graph()->CreateBasicBlock(); |
6940 HBasicBlock* other_map = graph()->CreateBasicBlock(); | 6958 HBasicBlock* other_map = graph()->CreateBasicBlock(); |
6941 HCompareMap* mapcompare = | 6959 HCompareMap* mapcompare = |
6942 New<HCompareMap>(object, map, this_map, other_map); | 6960 New<HCompareMap>(object, map, this_map, other_map); |
6943 FinishCurrentBlock(mapcompare); | 6961 FinishCurrentBlock(mapcompare); |
6944 | 6962 |
6945 set_current_block(this_map); | 6963 set_current_block(this_map); |
6946 HInstruction* access = NULL; | 6964 HInstruction* access = NULL; |
6947 if (IsDictionaryElementsKind(elements_kind)) { | 6965 if (IsDictionaryElementsKind(elements_kind)) { |
6948 access = AddInstruction(BuildKeyedGeneric(access_type, object, key, val)); | 6966 access = AddInstruction(BuildKeyedGeneric(access_type, expr, object, key, |
| 6967 val)); |
6949 } else { | 6968 } else { |
6950 ASSERT(IsFastElementsKind(elements_kind) || | 6969 ASSERT(IsFastElementsKind(elements_kind) || |
6951 IsExternalArrayElementsKind(elements_kind) || | 6970 IsExternalArrayElementsKind(elements_kind) || |
6952 IsFixedTypedArrayElementsKind(elements_kind)); | 6971 IsFixedTypedArrayElementsKind(elements_kind)); |
6953 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); | 6972 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); |
6954 // Happily, mapcompare is a checked object. | 6973 // Happily, mapcompare is a checked object. |
6955 access = BuildUncheckedMonomorphicElementAccess( | 6974 access = BuildUncheckedMonomorphicElementAccess( |
6956 mapcompare, key, val, | 6975 mapcompare, key, val, |
6957 map->instance_type() == JS_ARRAY_TYPE, | 6976 map->instance_type() == JS_ARRAY_TYPE, |
6958 elements_kind, access_type, | 6977 elements_kind, access_type, |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7009 force_generic = true; | 7028 force_generic = true; |
7010 monomorphic = false; | 7029 monomorphic = false; |
7011 break; | 7030 break; |
7012 } | 7031 } |
7013 } | 7032 } |
7014 } | 7033 } |
7015 | 7034 |
7016 if (monomorphic) { | 7035 if (monomorphic) { |
7017 Handle<Map> map = types->first(); | 7036 Handle<Map> map = types->first(); |
7018 if (map->has_slow_elements_kind() || !map->IsJSObjectMap()) { | 7037 if (map->has_slow_elements_kind() || !map->IsJSObjectMap()) { |
7019 instr = AddInstruction(BuildKeyedGeneric(access_type, obj, key, val)); | 7038 instr = AddInstruction(BuildKeyedGeneric(access_type, expr, obj, key, |
| 7039 val)); |
7020 } else { | 7040 } else { |
7021 BuildCheckHeapObject(obj); | 7041 BuildCheckHeapObject(obj); |
7022 instr = BuildMonomorphicElementAccess( | 7042 instr = BuildMonomorphicElementAccess( |
7023 obj, key, val, NULL, map, access_type, expr->GetStoreMode()); | 7043 obj, key, val, NULL, map, access_type, expr->GetStoreMode()); |
7024 } | 7044 } |
7025 } else if (!force_generic && (types != NULL && !types->is_empty())) { | 7045 } else if (!force_generic && (types != NULL && !types->is_empty())) { |
7026 return HandlePolymorphicElementAccess( | 7046 return HandlePolymorphicElementAccess( |
7027 obj, key, val, types, access_type, | 7047 expr, obj, key, val, types, access_type, |
7028 expr->GetStoreMode(), has_side_effects); | 7048 expr->GetStoreMode(), has_side_effects); |
7029 } else { | 7049 } else { |
7030 if (access_type == STORE) { | 7050 if (access_type == STORE) { |
7031 if (expr->IsAssignment() && | 7051 if (expr->IsAssignment() && |
7032 expr->AsAssignment()->HasNoTypeInformation()) { | 7052 expr->AsAssignment()->HasNoTypeInformation()) { |
7033 Add<HDeoptimize>("Insufficient type feedback for keyed store", | 7053 Add<HDeoptimize>("Insufficient type feedback for keyed store", |
7034 Deoptimizer::SOFT); | 7054 Deoptimizer::SOFT); |
7035 } | 7055 } |
7036 } else { | 7056 } else { |
7037 if (expr->AsProperty()->HasNoTypeInformation()) { | 7057 if (expr->AsProperty()->HasNoTypeInformation()) { |
7038 Add<HDeoptimize>("Insufficient type feedback for keyed load", | 7058 Add<HDeoptimize>("Insufficient type feedback for keyed load", |
7039 Deoptimizer::SOFT); | 7059 Deoptimizer::SOFT); |
7040 } | 7060 } |
7041 } | 7061 } |
7042 instr = AddInstruction(BuildKeyedGeneric(access_type, obj, key, val)); | 7062 instr = AddInstruction(BuildKeyedGeneric(access_type, expr, obj, key, val)); |
7043 } | 7063 } |
7044 *has_side_effects = instr->HasObservableSideEffects(); | 7064 *has_side_effects = instr->HasObservableSideEffects(); |
7045 return instr; | 7065 return instr; |
7046 } | 7066 } |
7047 | 7067 |
7048 | 7068 |
7049 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() { | 7069 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() { |
7050 // Outermost function already has arguments on the stack. | 7070 // Outermost function already has arguments on the stack. |
7051 if (function_state()->outer() == NULL) return; | 7071 if (function_state()->outer() == NULL) return; |
7052 | 7072 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7133 HValue* value, | 7153 HValue* value, |
7134 bool is_uninitialized) { | 7154 bool is_uninitialized) { |
7135 SmallMapList* types; | 7155 SmallMapList* types; |
7136 ComputeReceiverTypes(expr, object, &types, zone()); | 7156 ComputeReceiverTypes(expr, object, &types, zone()); |
7137 ASSERT(types != NULL); | 7157 ASSERT(types != NULL); |
7138 | 7158 |
7139 if (types->length() > 0) { | 7159 if (types->length() > 0) { |
7140 PropertyAccessInfo info(this, access, ToType(types->first()), name); | 7160 PropertyAccessInfo info(this, access, ToType(types->first()), name); |
7141 if (!info.CanAccessAsMonomorphic(types)) { | 7161 if (!info.CanAccessAsMonomorphic(types)) { |
7142 HandlePolymorphicNamedFieldAccess( | 7162 HandlePolymorphicNamedFieldAccess( |
7143 access, ast_id, return_id, object, value, types, name); | 7163 access, expr, ast_id, return_id, object, value, types, name); |
7144 return NULL; | 7164 return NULL; |
7145 } | 7165 } |
7146 | 7166 |
7147 HValue* checked_object; | 7167 HValue* checked_object; |
7148 // Type::Number() is only supported by polymorphic load/call handling. | 7168 // Type::Number() is only supported by polymorphic load/call handling. |
7149 ASSERT(!info.type()->Is(Type::Number())); | 7169 ASSERT(!info.type()->Is(Type::Number())); |
7150 BuildCheckHeapObject(object); | 7170 BuildCheckHeapObject(object); |
7151 if (AreStringTypes(types)) { | 7171 if (AreStringTypes(types)) { |
7152 checked_object = | 7172 checked_object = |
7153 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING); | 7173 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING); |
7154 } else { | 7174 } else { |
7155 checked_object = Add<HCheckMaps>(object, types); | 7175 checked_object = Add<HCheckMaps>(object, types); |
7156 } | 7176 } |
7157 return BuildMonomorphicAccess( | 7177 return BuildMonomorphicAccess( |
7158 &info, object, checked_object, value, ast_id, return_id); | 7178 &info, object, checked_object, value, ast_id, return_id); |
7159 } | 7179 } |
7160 | 7180 |
7161 return BuildNamedGeneric(access, object, name, value, is_uninitialized); | 7181 return BuildNamedGeneric(access, expr, object, name, value, is_uninitialized); |
7162 } | 7182 } |
7163 | 7183 |
7164 | 7184 |
7165 void HOptimizedGraphBuilder::PushLoad(Property* expr, | 7185 void HOptimizedGraphBuilder::PushLoad(Property* expr, |
7166 HValue* object, | 7186 HValue* object, |
7167 HValue* key) { | 7187 HValue* key) { |
7168 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); | 7188 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); |
7169 Push(object); | 7189 Push(object); |
7170 if (key != NULL) Push(key); | 7190 if (key != NULL) Push(key); |
7171 BuildLoad(expr, expr->LoadId()); | 7191 BuildLoad(expr, expr->LoadId()); |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7475 } | 7495 } |
7476 | 7496 |
7477 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 7497 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
7478 // know about and do not want to handle ones we've never seen. Otherwise | 7498 // know about and do not want to handle ones we've never seen. Otherwise |
7479 // use a generic IC. | 7499 // use a generic IC. |
7480 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { | 7500 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { |
7481 FinishExitWithHardDeoptimization("Unknown map in polymorphic call"); | 7501 FinishExitWithHardDeoptimization("Unknown map in polymorphic call"); |
7482 } else { | 7502 } else { |
7483 Property* prop = expr->expression()->AsProperty(); | 7503 Property* prop = expr->expression()->AsProperty(); |
7484 HInstruction* function = BuildNamedGeneric( | 7504 HInstruction* function = BuildNamedGeneric( |
7485 LOAD, receiver, name, NULL, prop->IsUninitialized()); | 7505 LOAD, prop, receiver, name, NULL, prop->IsUninitialized()); |
7486 AddInstruction(function); | 7506 AddInstruction(function); |
7487 Push(function); | 7507 Push(function); |
7488 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 7508 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); |
7489 | 7509 |
7490 environment()->SetExpressionStackAt(1, function); | 7510 environment()->SetExpressionStackAt(1, function); |
7491 environment()->SetExpressionStackAt(0, receiver); | 7511 environment()->SetExpressionStackAt(0, receiver); |
7492 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 7512 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
7493 | 7513 |
7494 CallFunctionFlags flags = receiver->type().IsJSObject() | 7514 CallFunctionFlags flags = receiver->type().IsJSObject() |
7495 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD; | 7515 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD; |
(...skipping 4879 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12375 if (ShouldProduceTraceOutput()) { | 12395 if (ShouldProduceTraceOutput()) { |
12376 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 12396 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
12377 } | 12397 } |
12378 | 12398 |
12379 #ifdef DEBUG | 12399 #ifdef DEBUG |
12380 graph_->Verify(false); // No full verify. | 12400 graph_->Verify(false); // No full verify. |
12381 #endif | 12401 #endif |
12382 } | 12402 } |
12383 | 12403 |
12384 } } // namespace v8::internal | 12404 } } // namespace v8::internal |
OLD | NEW |