| 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 |