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 5353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5364 return ast_context()->ReturnInstruction(instr, expr->id()); | 5364 return ast_context()->ReturnInstruction(instr, expr->id()); |
5365 } | 5365 } |
5366 } else { | 5366 } else { |
5367 HValue* global_object = Add<HLoadNamedField>( | 5367 HValue* global_object = Add<HLoadNamedField>( |
5368 context(), static_cast<HValue*>(NULL), | 5368 context(), static_cast<HValue*>(NULL), |
5369 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); | 5369 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); |
5370 HLoadGlobalGeneric* instr = | 5370 HLoadGlobalGeneric* instr = |
5371 New<HLoadGlobalGeneric>(global_object, | 5371 New<HLoadGlobalGeneric>(global_object, |
5372 variable->name(), | 5372 variable->name(), |
5373 ast_context()->is_for_typeof()); | 5373 ast_context()->is_for_typeof()); |
| 5374 if (FLAG_vector_ics) { |
| 5375 Handle<SharedFunctionInfo> current_shared = |
| 5376 function_state()->compilation_info()->shared_info(); |
| 5377 instr->SetVectorAndSlot( |
| 5378 handle(current_shared->feedback_vector(), isolate()), |
| 5379 expr->VariableFeedbackSlot()); |
| 5380 } |
5374 return ast_context()->ReturnInstruction(instr, expr->id()); | 5381 return ast_context()->ReturnInstruction(instr, expr->id()); |
5375 } | 5382 } |
5376 } | 5383 } |
5377 | 5384 |
5378 case Variable::PARAMETER: | 5385 case Variable::PARAMETER: |
5379 case Variable::LOCAL: { | 5386 case Variable::LOCAL: { |
5380 HValue* value = LookupAndMakeLive(variable); | 5387 HValue* value = LookupAndMakeLive(variable); |
5381 if (value == graph()->GetConstantHole()) { | 5388 if (value == graph()->GetConstantHole()) { |
5382 ASSERT(IsDeclaredVariableMode(variable->mode()) && | 5389 ASSERT(IsDeclaredVariableMode(variable->mode()) && |
5383 variable->mode() != VAR); | 5390 variable->mode() != VAR); |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5582 if (key->value()->IsInternalizedString()) { | 5589 if (key->value()->IsInternalizedString()) { |
5583 if (property->emit_store()) { | 5590 if (property->emit_store()) { |
5584 CHECK_ALIVE(VisitForValue(value)); | 5591 CHECK_ALIVE(VisitForValue(value)); |
5585 HValue* value = Pop(); | 5592 HValue* value = Pop(); |
5586 Handle<Map> map = property->GetReceiverType(); | 5593 Handle<Map> map = property->GetReceiverType(); |
5587 Handle<String> name = property->key()->AsPropertyName(); | 5594 Handle<String> name = property->key()->AsPropertyName(); |
5588 HInstruction* store; | 5595 HInstruction* store; |
5589 if (map.is_null()) { | 5596 if (map.is_null()) { |
5590 // If we don't know the monomorphic type, do a generic store. | 5597 // If we don't know the monomorphic type, do a generic store. |
5591 CHECK_ALIVE(store = BuildNamedGeneric( | 5598 CHECK_ALIVE(store = BuildNamedGeneric( |
5592 STORE, literal, name, value)); | 5599 STORE, NULL, literal, name, value)); |
5593 } else { | 5600 } else { |
5594 PropertyAccessInfo info(this, STORE, ToType(map), name); | 5601 PropertyAccessInfo info(this, STORE, ToType(map), name); |
5595 if (info.CanAccessMonomorphic()) { | 5602 if (info.CanAccessMonomorphic()) { |
5596 HValue* checked_literal = Add<HCheckMaps>(literal, map); | 5603 HValue* checked_literal = Add<HCheckMaps>(literal, map); |
5597 ASSERT(!info.lookup()->IsPropertyCallbacks()); | 5604 ASSERT(!info.lookup()->IsPropertyCallbacks()); |
5598 store = BuildMonomorphicAccess( | 5605 store = BuildMonomorphicAccess( |
5599 &info, literal, checked_literal, value, | 5606 &info, literal, checked_literal, value, |
5600 BailoutId::None(), BailoutId::None()); | 5607 BailoutId::None(), BailoutId::None()); |
5601 } else { | 5608 } else { |
5602 CHECK_ALIVE(store = BuildNamedGeneric( | 5609 CHECK_ALIVE(store = BuildNamedGeneric( |
5603 STORE, literal, name, value)); | 5610 STORE, NULL, literal, name, value)); |
5604 } | 5611 } |
5605 } | 5612 } |
5606 AddInstruction(store); | 5613 AddInstruction(store); |
5607 if (store->HasObservableSideEffects()) { | 5614 if (store->HasObservableSideEffects()) { |
5608 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE); | 5615 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE); |
5609 } | 5616 } |
5610 } else { | 5617 } else { |
5611 CHECK_ALIVE(VisitForEffect(value)); | 5618 CHECK_ALIVE(VisitForEffect(value)); |
5612 } | 5619 } |
5613 break; | 5620 break; |
(...skipping 592 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6206 if (info->IsLoad()) { | 6213 if (info->IsLoad()) { |
6207 return New<HConstant>(info->constant()); | 6214 return New<HConstant>(info->constant()); |
6208 } else { | 6215 } else { |
6209 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); | 6216 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); |
6210 } | 6217 } |
6211 } | 6218 } |
6212 | 6219 |
6213 | 6220 |
6214 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess( | 6221 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess( |
6215 PropertyAccessType access_type, | 6222 PropertyAccessType access_type, |
| 6223 Expression* expr, |
6216 BailoutId ast_id, | 6224 BailoutId ast_id, |
6217 BailoutId return_id, | 6225 BailoutId return_id, |
6218 HValue* object, | 6226 HValue* object, |
6219 HValue* value, | 6227 HValue* value, |
6220 SmallMapList* types, | 6228 SmallMapList* types, |
6221 Handle<String> name) { | 6229 Handle<String> name) { |
6222 // Something did not match; must use a polymorphic load. | 6230 // Something did not match; must use a polymorphic load. |
6223 int count = 0; | 6231 int count = 0; |
6224 HBasicBlock* join = NULL; | 6232 HBasicBlock* join = NULL; |
6225 HBasicBlock* number_block = NULL; | 6233 HBasicBlock* number_block = NULL; |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6319 if (current_block() != NULL) Goto(join); | 6327 if (current_block() != NULL) Goto(join); |
6320 set_current_block(if_false); | 6328 set_current_block(if_false); |
6321 } | 6329 } |
6322 | 6330 |
6323 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 6331 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
6324 // know about and do not want to handle ones we've never seen. Otherwise | 6332 // know about and do not want to handle ones we've never seen. Otherwise |
6325 // use a generic IC. | 6333 // use a generic IC. |
6326 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | 6334 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { |
6327 FinishExitWithHardDeoptimization("Uknown map in polymorphic access"); | 6335 FinishExitWithHardDeoptimization("Uknown map in polymorphic access"); |
6328 } else { | 6336 } else { |
6329 HInstruction* instr = BuildNamedGeneric(access_type, object, name, value); | 6337 HInstruction* instr = BuildNamedGeneric(access_type, expr, object, name, |
| 6338 value); |
6330 AddInstruction(instr); | 6339 AddInstruction(instr); |
6331 if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value); | 6340 if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value); |
6332 | 6341 |
6333 if (join != NULL) { | 6342 if (join != NULL) { |
6334 Goto(join); | 6343 Goto(join); |
6335 } else { | 6344 } else { |
6336 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6345 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
6337 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 6346 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
6338 return; | 6347 return; |
6339 } | 6348 } |
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6766 return Add<HConstant>(c_string->StringValue()->length()); | 6775 return Add<HConstant>(c_string->StringValue()->length()); |
6767 } | 6776 } |
6768 } | 6777 } |
6769 return Add<HLoadNamedField>(string, static_cast<HValue*>(NULL), | 6778 return Add<HLoadNamedField>(string, static_cast<HValue*>(NULL), |
6770 HObjectAccess::ForStringLength()); | 6779 HObjectAccess::ForStringLength()); |
6771 } | 6780 } |
6772 | 6781 |
6773 | 6782 |
6774 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric( | 6783 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric( |
6775 PropertyAccessType access_type, | 6784 PropertyAccessType access_type, |
| 6785 Expression* expr, |
6776 HValue* object, | 6786 HValue* object, |
6777 Handle<String> name, | 6787 Handle<String> name, |
6778 HValue* value, | 6788 HValue* value, |
6779 bool is_uninitialized) { | 6789 bool is_uninitialized) { |
6780 if (is_uninitialized) { | 6790 if (is_uninitialized) { |
6781 Add<HDeoptimize>("Insufficient type feedback for generic named access", | 6791 Add<HDeoptimize>("Insufficient type feedback for generic named access", |
6782 Deoptimizer::SOFT); | 6792 Deoptimizer::SOFT); |
6783 } | 6793 } |
6784 if (access_type == LOAD) { | 6794 if (access_type == LOAD) { |
6785 return New<HLoadNamedGeneric>(object, name); | 6795 HLoadNamedGeneric* result = New<HLoadNamedGeneric>(object, name); |
| 6796 if (FLAG_vector_ics) { |
| 6797 Handle<SharedFunctionInfo> current_shared = |
| 6798 function_state()->compilation_info()->shared_info(); |
| 6799 result->SetVectorAndSlot( |
| 6800 handle(current_shared->feedback_vector(), isolate()), |
| 6801 expr->AsProperty()->PropertyFeedbackSlot()); |
| 6802 } |
| 6803 return result; |
6786 } else { | 6804 } else { |
6787 return New<HStoreNamedGeneric>(object, name, value, function_strict_mode()); | 6805 return New<HStoreNamedGeneric>(object, name, value, function_strict_mode()); |
6788 } | 6806 } |
6789 } | 6807 } |
6790 | 6808 |
6791 | 6809 |
6792 | 6810 |
6793 HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric( | 6811 HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric( |
6794 PropertyAccessType access_type, | 6812 PropertyAccessType access_type, |
| 6813 Expression* expr, |
6795 HValue* object, | 6814 HValue* object, |
6796 HValue* key, | 6815 HValue* key, |
6797 HValue* value) { | 6816 HValue* value) { |
6798 if (access_type == LOAD) { | 6817 if (access_type == LOAD) { |
6799 return New<HLoadKeyedGeneric>(object, key); | 6818 HLoadKeyedGeneric* result = New<HLoadKeyedGeneric>(object, key); |
| 6819 if (FLAG_vector_ics) { |
| 6820 Handle<SharedFunctionInfo> current_shared = |
| 6821 function_state()->compilation_info()->shared_info(); |
| 6822 result->SetVectorAndSlot( |
| 6823 handle(current_shared->feedback_vector(), isolate()), |
| 6824 expr->AsProperty()->PropertyFeedbackSlot()); |
| 6825 } |
| 6826 return result; |
6800 } else { | 6827 } else { |
6801 return New<HStoreKeyedGeneric>(object, key, value, function_strict_mode()); | 6828 return New<HStoreKeyedGeneric>(object, key, value, function_strict_mode()); |
6802 } | 6829 } |
6803 } | 6830 } |
6804 | 6831 |
6805 | 6832 |
6806 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) { | 6833 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) { |
6807 // Loads from a "stock" fast holey double arrays can elide the hole check. | 6834 // Loads from a "stock" fast holey double arrays can elide the hole check. |
6808 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; | 6835 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; |
6809 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && | 6836 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6917 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( | 6944 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( |
6918 checked_object, key, val, | 6945 checked_object, key, val, |
6919 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, | 6946 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, |
6920 consolidated_elements_kind, | 6947 consolidated_elements_kind, |
6921 LOAD, NEVER_RETURN_HOLE, STANDARD_STORE); | 6948 LOAD, NEVER_RETURN_HOLE, STANDARD_STORE); |
6922 return instr; | 6949 return instr; |
6923 } | 6950 } |
6924 | 6951 |
6925 | 6952 |
6926 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( | 6953 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( |
| 6954 Expression* expr, |
6927 HValue* object, | 6955 HValue* object, |
6928 HValue* key, | 6956 HValue* key, |
6929 HValue* val, | 6957 HValue* val, |
6930 SmallMapList* maps, | 6958 SmallMapList* maps, |
6931 PropertyAccessType access_type, | 6959 PropertyAccessType access_type, |
6932 KeyedAccessStoreMode store_mode, | 6960 KeyedAccessStoreMode store_mode, |
6933 bool* has_side_effects) { | 6961 bool* has_side_effects) { |
6934 *has_side_effects = false; | 6962 *has_side_effects = false; |
6935 BuildCheckHeapObject(object); | 6963 BuildCheckHeapObject(object); |
6936 | 6964 |
(...skipping 11 matching lines...) Expand all Loading... |
6948 // Collect possible transition targets. | 6976 // Collect possible transition targets. |
6949 MapHandleList possible_transitioned_maps(maps->length()); | 6977 MapHandleList possible_transitioned_maps(maps->length()); |
6950 for (int i = 0; i < maps->length(); ++i) { | 6978 for (int i = 0; i < maps->length(); ++i) { |
6951 Handle<Map> map = maps->at(i); | 6979 Handle<Map> map = maps->at(i); |
6952 ElementsKind elements_kind = map->elements_kind(); | 6980 ElementsKind elements_kind = map->elements_kind(); |
6953 if (IsFastElementsKind(elements_kind) && | 6981 if (IsFastElementsKind(elements_kind) && |
6954 elements_kind != GetInitialFastElementsKind()) { | 6982 elements_kind != GetInitialFastElementsKind()) { |
6955 possible_transitioned_maps.Add(map); | 6983 possible_transitioned_maps.Add(map); |
6956 } | 6984 } |
6957 if (elements_kind == SLOPPY_ARGUMENTS_ELEMENTS) { | 6985 if (elements_kind == SLOPPY_ARGUMENTS_ELEMENTS) { |
6958 HInstruction* result = BuildKeyedGeneric(access_type, object, key, val); | 6986 HInstruction* result = BuildKeyedGeneric(access_type, expr, object, key, |
| 6987 val); |
6959 *has_side_effects = result->HasObservableSideEffects(); | 6988 *has_side_effects = result->HasObservableSideEffects(); |
6960 return AddInstruction(result); | 6989 return AddInstruction(result); |
6961 } | 6990 } |
6962 } | 6991 } |
6963 // Get transition target for each map (NULL == no transition). | 6992 // Get transition target for each map (NULL == no transition). |
6964 for (int i = 0; i < maps->length(); ++i) { | 6993 for (int i = 0; i < maps->length(); ++i) { |
6965 Handle<Map> map = maps->at(i); | 6994 Handle<Map> map = maps->at(i); |
6966 Handle<Map> transitioned_map = | 6995 Handle<Map> transitioned_map = |
6967 map->FindTransitionedMap(&possible_transitioned_maps); | 6996 map->FindTransitionedMap(&possible_transitioned_maps); |
6968 transition_target.Add(transitioned_map); | 6997 transition_target.Add(transitioned_map); |
(...skipping 16 matching lines...) Expand all Loading... |
6985 } | 7014 } |
6986 | 7015 |
6987 // If only one map is left after transitioning, handle this case | 7016 // If only one map is left after transitioning, handle this case |
6988 // monomorphically. | 7017 // monomorphically. |
6989 ASSERT(untransitionable_maps.length() >= 1); | 7018 ASSERT(untransitionable_maps.length() >= 1); |
6990 if (untransitionable_maps.length() == 1) { | 7019 if (untransitionable_maps.length() == 1) { |
6991 Handle<Map> untransitionable_map = untransitionable_maps[0]; | 7020 Handle<Map> untransitionable_map = untransitionable_maps[0]; |
6992 HInstruction* instr = NULL; | 7021 HInstruction* instr = NULL; |
6993 if (untransitionable_map->has_slow_elements_kind() || | 7022 if (untransitionable_map->has_slow_elements_kind() || |
6994 !untransitionable_map->IsJSObjectMap()) { | 7023 !untransitionable_map->IsJSObjectMap()) { |
6995 instr = AddInstruction(BuildKeyedGeneric(access_type, object, key, val)); | 7024 instr = AddInstruction(BuildKeyedGeneric(access_type, expr, object, key, |
| 7025 val)); |
6996 } else { | 7026 } else { |
6997 instr = BuildMonomorphicElementAccess( | 7027 instr = BuildMonomorphicElementAccess( |
6998 object, key, val, transition, untransitionable_map, access_type, | 7028 object, key, val, transition, untransitionable_map, access_type, |
6999 store_mode); | 7029 store_mode); |
7000 } | 7030 } |
7001 *has_side_effects |= instr->HasObservableSideEffects(); | 7031 *has_side_effects |= instr->HasObservableSideEffects(); |
7002 return access_type == STORE ? NULL : instr; | 7032 return access_type == STORE ? NULL : instr; |
7003 } | 7033 } |
7004 | 7034 |
7005 HBasicBlock* join = graph()->CreateBasicBlock(); | 7035 HBasicBlock* join = graph()->CreateBasicBlock(); |
7006 | 7036 |
7007 for (int i = 0; i < untransitionable_maps.length(); ++i) { | 7037 for (int i = 0; i < untransitionable_maps.length(); ++i) { |
7008 Handle<Map> map = untransitionable_maps[i]; | 7038 Handle<Map> map = untransitionable_maps[i]; |
7009 if (!map->IsJSObjectMap()) continue; | 7039 if (!map->IsJSObjectMap()) continue; |
7010 ElementsKind elements_kind = map->elements_kind(); | 7040 ElementsKind elements_kind = map->elements_kind(); |
7011 HBasicBlock* this_map = graph()->CreateBasicBlock(); | 7041 HBasicBlock* this_map = graph()->CreateBasicBlock(); |
7012 HBasicBlock* other_map = graph()->CreateBasicBlock(); | 7042 HBasicBlock* other_map = graph()->CreateBasicBlock(); |
7013 HCompareMap* mapcompare = | 7043 HCompareMap* mapcompare = |
7014 New<HCompareMap>(object, map, this_map, other_map); | 7044 New<HCompareMap>(object, map, this_map, other_map); |
7015 FinishCurrentBlock(mapcompare); | 7045 FinishCurrentBlock(mapcompare); |
7016 | 7046 |
7017 set_current_block(this_map); | 7047 set_current_block(this_map); |
7018 HInstruction* access = NULL; | 7048 HInstruction* access = NULL; |
7019 if (IsDictionaryElementsKind(elements_kind)) { | 7049 if (IsDictionaryElementsKind(elements_kind)) { |
7020 access = AddInstruction(BuildKeyedGeneric(access_type, object, key, val)); | 7050 access = AddInstruction(BuildKeyedGeneric(access_type, expr, object, key, |
| 7051 val)); |
7021 } else { | 7052 } else { |
7022 ASSERT(IsFastElementsKind(elements_kind) || | 7053 ASSERT(IsFastElementsKind(elements_kind) || |
7023 IsExternalArrayElementsKind(elements_kind) || | 7054 IsExternalArrayElementsKind(elements_kind) || |
7024 IsFixedTypedArrayElementsKind(elements_kind)); | 7055 IsFixedTypedArrayElementsKind(elements_kind)); |
7025 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); | 7056 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); |
7026 // Happily, mapcompare is a checked object. | 7057 // Happily, mapcompare is a checked object. |
7027 access = BuildUncheckedMonomorphicElementAccess( | 7058 access = BuildUncheckedMonomorphicElementAccess( |
7028 mapcompare, key, val, | 7059 mapcompare, key, val, |
7029 map->instance_type() == JS_ARRAY_TYPE, | 7060 map->instance_type() == JS_ARRAY_TYPE, |
7030 elements_kind, access_type, | 7061 elements_kind, access_type, |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7081 force_generic = true; | 7112 force_generic = true; |
7082 monomorphic = false; | 7113 monomorphic = false; |
7083 break; | 7114 break; |
7084 } | 7115 } |
7085 } | 7116 } |
7086 } | 7117 } |
7087 | 7118 |
7088 if (monomorphic) { | 7119 if (monomorphic) { |
7089 Handle<Map> map = types->first(); | 7120 Handle<Map> map = types->first(); |
7090 if (map->has_slow_elements_kind() || !map->IsJSObjectMap()) { | 7121 if (map->has_slow_elements_kind() || !map->IsJSObjectMap()) { |
7091 instr = AddInstruction(BuildKeyedGeneric(access_type, obj, key, val)); | 7122 instr = AddInstruction(BuildKeyedGeneric(access_type, expr, obj, key, |
| 7123 val)); |
7092 } else { | 7124 } else { |
7093 BuildCheckHeapObject(obj); | 7125 BuildCheckHeapObject(obj); |
7094 instr = BuildMonomorphicElementAccess( | 7126 instr = BuildMonomorphicElementAccess( |
7095 obj, key, val, NULL, map, access_type, expr->GetStoreMode()); | 7127 obj, key, val, NULL, map, access_type, expr->GetStoreMode()); |
7096 } | 7128 } |
7097 } else if (!force_generic && (types != NULL && !types->is_empty())) { | 7129 } else if (!force_generic && (types != NULL && !types->is_empty())) { |
7098 return HandlePolymorphicElementAccess( | 7130 return HandlePolymorphicElementAccess( |
7099 obj, key, val, types, access_type, | 7131 expr, obj, key, val, types, access_type, |
7100 expr->GetStoreMode(), has_side_effects); | 7132 expr->GetStoreMode(), has_side_effects); |
7101 } else { | 7133 } else { |
7102 if (access_type == STORE) { | 7134 if (access_type == STORE) { |
7103 if (expr->IsAssignment() && | 7135 if (expr->IsAssignment() && |
7104 expr->AsAssignment()->HasNoTypeInformation()) { | 7136 expr->AsAssignment()->HasNoTypeInformation()) { |
7105 Add<HDeoptimize>("Insufficient type feedback for keyed store", | 7137 Add<HDeoptimize>("Insufficient type feedback for keyed store", |
7106 Deoptimizer::SOFT); | 7138 Deoptimizer::SOFT); |
7107 } | 7139 } |
7108 } else { | 7140 } else { |
7109 if (expr->AsProperty()->HasNoTypeInformation()) { | 7141 if (expr->AsProperty()->HasNoTypeInformation()) { |
7110 Add<HDeoptimize>("Insufficient type feedback for keyed load", | 7142 Add<HDeoptimize>("Insufficient type feedback for keyed load", |
7111 Deoptimizer::SOFT); | 7143 Deoptimizer::SOFT); |
7112 } | 7144 } |
7113 } | 7145 } |
7114 instr = AddInstruction(BuildKeyedGeneric(access_type, obj, key, val)); | 7146 instr = AddInstruction(BuildKeyedGeneric(access_type, expr, obj, key, val)); |
7115 } | 7147 } |
7116 *has_side_effects = instr->HasObservableSideEffects(); | 7148 *has_side_effects = instr->HasObservableSideEffects(); |
7117 return instr; | 7149 return instr; |
7118 } | 7150 } |
7119 | 7151 |
7120 | 7152 |
7121 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() { | 7153 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() { |
7122 // Outermost function already has arguments on the stack. | 7154 // Outermost function already has arguments on the stack. |
7123 if (function_state()->outer() == NULL) return; | 7155 if (function_state()->outer() == NULL) return; |
7124 | 7156 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7205 HValue* value, | 7237 HValue* value, |
7206 bool is_uninitialized) { | 7238 bool is_uninitialized) { |
7207 SmallMapList* types; | 7239 SmallMapList* types; |
7208 ComputeReceiverTypes(expr, object, &types, zone()); | 7240 ComputeReceiverTypes(expr, object, &types, zone()); |
7209 ASSERT(types != NULL); | 7241 ASSERT(types != NULL); |
7210 | 7242 |
7211 if (types->length() > 0) { | 7243 if (types->length() > 0) { |
7212 PropertyAccessInfo info(this, access, ToType(types->first()), name); | 7244 PropertyAccessInfo info(this, access, ToType(types->first()), name); |
7213 if (!info.CanAccessAsMonomorphic(types)) { | 7245 if (!info.CanAccessAsMonomorphic(types)) { |
7214 HandlePolymorphicNamedFieldAccess( | 7246 HandlePolymorphicNamedFieldAccess( |
7215 access, ast_id, return_id, object, value, types, name); | 7247 access, expr, ast_id, return_id, object, value, types, name); |
7216 return NULL; | 7248 return NULL; |
7217 } | 7249 } |
7218 | 7250 |
7219 HValue* checked_object; | 7251 HValue* checked_object; |
7220 // Type::Number() is only supported by polymorphic load/call handling. | 7252 // Type::Number() is only supported by polymorphic load/call handling. |
7221 ASSERT(!info.type()->Is(Type::Number())); | 7253 ASSERT(!info.type()->Is(Type::Number())); |
7222 BuildCheckHeapObject(object); | 7254 BuildCheckHeapObject(object); |
7223 if (AreStringTypes(types)) { | 7255 if (AreStringTypes(types)) { |
7224 checked_object = | 7256 checked_object = |
7225 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING); | 7257 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING); |
7226 } else { | 7258 } else { |
7227 checked_object = Add<HCheckMaps>(object, types); | 7259 checked_object = Add<HCheckMaps>(object, types); |
7228 } | 7260 } |
7229 return BuildMonomorphicAccess( | 7261 return BuildMonomorphicAccess( |
7230 &info, object, checked_object, value, ast_id, return_id); | 7262 &info, object, checked_object, value, ast_id, return_id); |
7231 } | 7263 } |
7232 | 7264 |
7233 return BuildNamedGeneric(access, object, name, value, is_uninitialized); | 7265 return BuildNamedGeneric(access, expr, object, name, value, is_uninitialized); |
7234 } | 7266 } |
7235 | 7267 |
7236 | 7268 |
7237 void HOptimizedGraphBuilder::PushLoad(Property* expr, | 7269 void HOptimizedGraphBuilder::PushLoad(Property* expr, |
7238 HValue* object, | 7270 HValue* object, |
7239 HValue* key) { | 7271 HValue* key) { |
7240 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); | 7272 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); |
7241 Push(object); | 7273 Push(object); |
7242 if (key != NULL) Push(key); | 7274 if (key != NULL) Push(key); |
7243 BuildLoad(expr, expr->LoadId()); | 7275 BuildLoad(expr, expr->LoadId()); |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7552 } | 7584 } |
7553 | 7585 |
7554 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 7586 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
7555 // know about and do not want to handle ones we've never seen. Otherwise | 7587 // know about and do not want to handle ones we've never seen. Otherwise |
7556 // use a generic IC. | 7588 // use a generic IC. |
7557 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { | 7589 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { |
7558 FinishExitWithHardDeoptimization("Unknown map in polymorphic call"); | 7590 FinishExitWithHardDeoptimization("Unknown map in polymorphic call"); |
7559 } else { | 7591 } else { |
7560 Property* prop = expr->expression()->AsProperty(); | 7592 Property* prop = expr->expression()->AsProperty(); |
7561 HInstruction* function = BuildNamedGeneric( | 7593 HInstruction* function = BuildNamedGeneric( |
7562 LOAD, receiver, name, NULL, prop->IsUninitialized()); | 7594 LOAD, prop, receiver, name, NULL, prop->IsUninitialized()); |
7563 AddInstruction(function); | 7595 AddInstruction(function); |
7564 Push(function); | 7596 Push(function); |
7565 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 7597 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); |
7566 | 7598 |
7567 environment()->SetExpressionStackAt(1, function); | 7599 environment()->SetExpressionStackAt(1, function); |
7568 environment()->SetExpressionStackAt(0, receiver); | 7600 environment()->SetExpressionStackAt(0, receiver); |
7569 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 7601 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
7570 | 7602 |
7571 CallFunctionFlags flags = receiver->type().IsJSObject() | 7603 CallFunctionFlags flags = receiver->type().IsJSObject() |
7572 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD; | 7604 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD; |
(...skipping 4865 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12438 if (ShouldProduceTraceOutput()) { | 12470 if (ShouldProduceTraceOutput()) { |
12439 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 12471 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
12440 } | 12472 } |
12441 | 12473 |
12442 #ifdef DEBUG | 12474 #ifdef DEBUG |
12443 graph_->Verify(false); // No full verify. | 12475 graph_->Verify(false); // No full verify. |
12444 #endif | 12476 #endif |
12445 } | 12477 } |
12446 | 12478 |
12447 } } // namespace v8::internal | 12479 } } // namespace v8::internal |
OLD | NEW |