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

Side by Side Diff: src/hydrogen.cc

Issue 18209023: Hydrogen array accesses: switch from elements_kind to map based polymorphism (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | 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 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 5874 matching lines...) Expand 10 before | Expand all | Expand 10 after
5885 HValue* val, 5885 HValue* val,
5886 Expression* prop, 5886 Expression* prop,
5887 BailoutId ast_id, 5887 BailoutId ast_id,
5888 int position, 5888 int position,
5889 bool is_store, 5889 bool is_store,
5890 KeyedAccessStoreMode store_mode, 5890 KeyedAccessStoreMode store_mode,
5891 bool* has_side_effects) { 5891 bool* has_side_effects) {
5892 *has_side_effects = false; 5892 *has_side_effects = false;
5893 BuildCheckHeapObject(object); 5893 BuildCheckHeapObject(object);
5894 SmallMapList* maps = prop->GetReceiverTypes(); 5894 SmallMapList* maps = prop->GetReceiverTypes();
5895 bool todo_external_array = false;
5896 5895
5897 if (!is_store) { 5896 if (!is_store) {
5898 HInstruction* consolidated_load = 5897 HInstruction* consolidated_load =
5899 TryBuildConsolidatedElementLoad(object, key, val, maps); 5898 TryBuildConsolidatedElementLoad(object, key, val, maps);
5900 if (consolidated_load != NULL) { 5899 if (consolidated_load != NULL) {
5901 *has_side_effects |= consolidated_load->HasObservableSideEffects(); 5900 *has_side_effects |= consolidated_load->HasObservableSideEffects();
5902 if (position != RelocInfo::kNoPosition) { 5901 if (position != RelocInfo::kNoPosition) {
5903 consolidated_load->set_position(position); 5902 consolidated_load->set_position(position);
5904 } 5903 }
5905 return consolidated_load; 5904 return consolidated_load;
5906 } 5905 }
5907 } 5906 }
5908 5907
5909 static const int kNumElementTypes = kElementsKindCount;
5910 bool type_todo[kNumElementTypes];
5911 for (int i = 0; i < kNumElementTypes; ++i) {
5912 type_todo[i] = false;
5913 }
5914
5915 // Elements_kind transition support. 5908 // Elements_kind transition support.
5916 MapHandleList transition_target(maps->length()); 5909 MapHandleList transition_target(maps->length());
5917 // Collect possible transition targets. 5910 // Collect possible transition targets.
5918 MapHandleList possible_transitioned_maps(maps->length()); 5911 MapHandleList possible_transitioned_maps(maps->length());
5919 for (int i = 0; i < maps->length(); ++i) { 5912 for (int i = 0; i < maps->length(); ++i) {
5920 Handle<Map> map = maps->at(i); 5913 Handle<Map> map = maps->at(i);
5921 ElementsKind elements_kind = map->elements_kind(); 5914 ElementsKind elements_kind = map->elements_kind();
5922 if (IsFastElementsKind(elements_kind) && 5915 if (IsFastElementsKind(elements_kind) &&
5923 elements_kind != GetInitialFastElementsKind()) { 5916 elements_kind != GetInitialFastElementsKind()) {
5924 possible_transitioned_maps.Add(map); 5917 possible_transitioned_maps.Add(map);
5925 } 5918 }
5926 } 5919 }
5927 // Get transition target for each map (NULL == no transition). 5920 // Get transition target for each map (NULL == no transition).
5928 for (int i = 0; i < maps->length(); ++i) { 5921 for (int i = 0; i < maps->length(); ++i) {
5929 Handle<Map> map = maps->at(i); 5922 Handle<Map> map = maps->at(i);
5930 Handle<Map> transitioned_map = 5923 Handle<Map> transitioned_map =
5931 map->FindTransitionedMap(&possible_transitioned_maps); 5924 map->FindTransitionedMap(&possible_transitioned_maps);
5932 transition_target.Add(transitioned_map); 5925 transition_target.Add(transitioned_map);
5933 } 5926 }
5934 5927
5935 int num_untransitionable_maps = 0; 5928 MapHandleList untransitionable_maps(maps->length());
5936 Handle<Map> untransitionable_map;
5937 HTransitionElementsKind* transition = NULL; 5929 HTransitionElementsKind* transition = NULL;
5938 for (int i = 0; i < maps->length(); ++i) { 5930 for (int i = 0; i < maps->length(); ++i) {
5939 Handle<Map> map = maps->at(i); 5931 Handle<Map> map = maps->at(i);
5940 ASSERT(map->IsMap()); 5932 ASSERT(map->IsMap());
5941 if (!transition_target.at(i).is_null()) { 5933 if (!transition_target.at(i).is_null()) {
5942 ASSERT(Map::IsValidElementsTransition( 5934 ASSERT(Map::IsValidElementsTransition(
5943 map->elements_kind(), 5935 map->elements_kind(),
5944 transition_target.at(i)->elements_kind())); 5936 transition_target.at(i)->elements_kind()));
5945 HValue* context = environment()->LookupContext(); 5937 HValue* context = environment()->LookupContext();
5946 transition = Add<HTransitionElementsKind>(context, object, map, 5938 transition = Add<HTransitionElementsKind>(context, object, map,
5947 transition_target.at(i)); 5939 transition_target.at(i));
5948 } else { 5940 } else {
5949 type_todo[map->elements_kind()] = true; 5941 untransitionable_maps.Add(map);
5950 if (IsExternalArrayElementsKind(map->elements_kind())) {
5951 todo_external_array = true;
5952 }
5953 num_untransitionable_maps++;
5954 untransitionable_map = map;
5955 } 5942 }
5956 } 5943 }
5957 5944
5958 // If only one map is left after transitioning, handle this case 5945 // If only one map is left after transitioning, handle this case
5959 // monomorphically. 5946 // monomorphically.
5960 ASSERT(num_untransitionable_maps >= 1); 5947 ASSERT(untransitionable_maps.length() >= 1);
5961 if (num_untransitionable_maps == 1) { 5948 if (untransitionable_maps.length() == 1) {
5949 Handle<Map> untransitionable_map = untransitionable_maps[0];
5962 HInstruction* instr = NULL; 5950 HInstruction* instr = NULL;
5963 if (untransitionable_map->has_slow_elements_kind()) { 5951 if (untransitionable_map->has_slow_elements_kind()) {
5964 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) 5952 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val)
5965 : BuildLoadKeyedGeneric(object, key)); 5953 : BuildLoadKeyedGeneric(object, key));
5966 } else { 5954 } else {
5967 instr = BuildMonomorphicElementAccess( 5955 instr = BuildMonomorphicElementAccess(
5968 object, key, val, transition, untransitionable_map, is_store, 5956 object, key, val, transition, untransitionable_map, is_store,
5969 store_mode); 5957 store_mode);
5970 } 5958 }
5971 *has_side_effects |= instr->HasObservableSideEffects(); 5959 *has_side_effects |= instr->HasObservableSideEffects();
5972 if (position != RelocInfo::kNoPosition) instr->set_position(position); 5960 if (position != RelocInfo::kNoPosition) instr->set_position(position);
5973 return is_store ? NULL : instr; 5961 return is_store ? NULL : instr;
5974 } 5962 }
5975 5963
5976 HInstruction* checkspec = 5964 HInstruction* checkspec =
5977 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone())); 5965 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone()));
5978 HBasicBlock* join = graph()->CreateBasicBlock(); 5966 HBasicBlock* join = graph()->CreateBasicBlock();
5979 5967
5980 HInstruction* elements_kind_instr = Add<HElementsKind>(object);
5981 HInstruction* elements = AddLoadElements(object, checkspec); 5968 HInstruction* elements = AddLoadElements(object, checkspec);
5982 HLoadExternalArrayPointer* external_elements = NULL;
5983 HInstruction* checked_key = NULL;
5984 5969
5985 // Generated code assumes that FAST_* and DICTIONARY_ELEMENTS ElementsKinds 5970 for (int i = 0; i < untransitionable_maps.length(); ++i) {
5986 // are handled before external arrays. 5971 Handle<Map> map = untransitionable_maps[i];
5987 STATIC_ASSERT(FAST_SMI_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); 5972 ElementsKind elements_kind = map->elements_kind();
5988 STATIC_ASSERT(FAST_HOLEY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); 5973 HBasicBlock* this_map = graph()->CreateBasicBlock();
5989 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); 5974 HBasicBlock* other_map = graph()->CreateBasicBlock();
5990 STATIC_ASSERT(DICTIONARY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); 5975 HCompareMap* mapcompare =
5976 new(zone()) HCompareMap(object, map, this_map, other_map);
5977 current_block()->Finish(mapcompare);
5991 5978
5992 for (ElementsKind elements_kind = FIRST_ELEMENTS_KIND; 5979 set_current_block(this_map);
5993 elements_kind <= LAST_ELEMENTS_KIND; 5980 HInstruction* checked_key = NULL;
5994 elements_kind = ElementsKind(elements_kind + 1)) { 5981 HInstruction* access = NULL;
5995 // After having handled FAST_* and DICTIONARY_ELEMENTS, we need to add some 5982 if (IsFastElementsKind(elements_kind)) {
5996 // code that's executed for all external array cases. 5983 if (is_store && !IsFastDoubleElementsKind(elements_kind)) {
5997 STATIC_ASSERT(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == 5984 AddInstruction(HCheckMaps::New(
5998 LAST_ELEMENTS_KIND); 5985 elements, isolate()->factory()->fixed_array_map(),
5999 if (elements_kind == FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND 5986 zone(), mapcompare));
6000 && todo_external_array) { 5987 }
5988 if (map->IsJSArray()) {
5989 HInstruction* length = AddLoad(object, HObjectAccess::ForArrayLength(),
5990 mapcompare, Representation::Smi());
5991 length->set_type(HType::Smi());
5992 checked_key = Add<HBoundsCheck>(key, length);
5993 } else {
5994 HInstruction* length = AddLoadFixedArrayLength(elements);
5995 checked_key = Add<HBoundsCheck>(key, length);
5996 }
5997 access = AddInstruction(BuildFastElementAccess(
5998 elements, checked_key, val, mapcompare,
5999 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE));
6000 } else if (IsDictionaryElementsKind(elements_kind)) {
6001 if (is_store) {
6002 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val));
6003 } else {
6004 access = AddInstruction(BuildLoadKeyedGeneric(object, key));
6005 }
6006 } else {
6007 ASSERT(IsExternalArrayElementsKind(elements_kind));
6001 HInstruction* length = AddLoadFixedArrayLength(elements); 6008 HInstruction* length = AddLoadFixedArrayLength(elements);
6002 checked_key = Add<HBoundsCheck>(key, length); 6009 checked_key = Add<HBoundsCheck>(key, length);
6003 external_elements = Add<HLoadExternalArrayPointer>(elements); 6010 HLoadExternalArrayPointer* external_elements =
6011 Add<HLoadExternalArrayPointer>(elements);
6012 access = AddInstruction(BuildExternalArrayElementAccess(
6013 external_elements, checked_key, val,
6014 mapcompare, elements_kind, is_store));
6004 } 6015 }
6005 if (type_todo[elements_kind]) { 6016 *has_side_effects |= access->HasObservableSideEffects();
6006 HBasicBlock* if_true = graph()->CreateBasicBlock(); 6017 // The caller will use has_side_effects and add a correct Simulate.
6007 HBasicBlock* if_false = graph()->CreateBasicBlock(); 6018 access->SetFlag(HValue::kHasNoObservableSideEffects);
6008 HCompareConstantEqAndBranch* elements_kind_branch = 6019 if (position != RelocInfo::kNoPosition) access->set_position(position);
6009 new(zone()) HCompareConstantEqAndBranch( 6020 if (!is_store) {
6010 elements_kind_instr, elements_kind, Token::EQ_STRICT); 6021 Push(access);
6011 elements_kind_branch->SetSuccessorAt(0, if_true);
6012 elements_kind_branch->SetSuccessorAt(1, if_false);
6013 current_block()->Finish(elements_kind_branch);
6014
6015 set_current_block(if_true);
6016 HInstruction* access;
6017 if (IsFastElementsKind(elements_kind)) {
6018 if (is_store && !IsFastDoubleElementsKind(elements_kind)) {
6019 AddInstruction(HCheckMaps::New(
6020 elements, isolate()->factory()->fixed_array_map(),
6021 zone(), elements_kind_branch));
6022 }
6023 // TODO(jkummerow): The need for these two blocks could be avoided
6024 // in one of two ways:
6025 // (1) Introduce ElementsKinds for JSArrays that are distinct from
6026 // those for fast objects.
6027 // (2) Put the common instructions into a third "join" block. This
6028 // requires additional AST IDs that we can deopt to from inside
6029 // that join block. They must be added to the Property class (when
6030 // it's a keyed property) and registered in the full codegen.
6031 HBasicBlock* if_jsarray = graph()->CreateBasicBlock();
6032 HBasicBlock* if_fastobject = graph()->CreateBasicBlock();
6033 HHasInstanceTypeAndBranch* typecheck =
6034 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE);
6035 typecheck->SetSuccessorAt(0, if_jsarray);
6036 typecheck->SetSuccessorAt(1, if_fastobject);
6037 current_block()->Finish(typecheck);
6038
6039 set_current_block(if_jsarray);
6040 HInstruction* length = AddLoad(object, HObjectAccess::ForArrayLength(),
6041 typecheck, Representation::Smi());
6042 length->set_type(HType::Smi());
6043
6044 checked_key = Add<HBoundsCheck>(key, length);
6045 access = AddInstruction(BuildFastElementAccess(
6046 elements, checked_key, val, elements_kind_branch,
6047 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE));
6048 if (!is_store) {
6049 Push(access);
6050 }
6051
6052 *has_side_effects |= access->HasObservableSideEffects();
6053 // The caller will use has_side_effects and add correct Simulate.
6054 access->SetFlag(HValue::kHasNoObservableSideEffects);
6055 if (position != -1) {
6056 access->set_position(position);
6057 }
6058 if_jsarray->GotoNoSimulate(join);
6059
6060 set_current_block(if_fastobject);
6061 length = AddLoadFixedArrayLength(elements);
6062 checked_key = Add<HBoundsCheck>(key, length);
6063 access = AddInstruction(BuildFastElementAccess(
6064 elements, checked_key, val, elements_kind_branch,
6065 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE));
6066 } else if (elements_kind == DICTIONARY_ELEMENTS) {
6067 if (is_store) {
6068 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val));
6069 } else {
6070 access = AddInstruction(BuildLoadKeyedGeneric(object, key));
6071 }
6072 } else { // External array elements.
6073 access = AddInstruction(BuildExternalArrayElementAccess(
6074 external_elements, checked_key, val,
6075 elements_kind_branch, elements_kind, is_store));
6076 }
6077 *has_side_effects |= access->HasObservableSideEffects();
6078 // The caller will use has_side_effects and add correct Simulate.
6079 access->SetFlag(HValue::kHasNoObservableSideEffects);
6080 if (position != RelocInfo::kNoPosition) access->set_position(position);
6081 if (!is_store) {
6082 Push(access);
6083 }
6084 current_block()->GotoNoSimulate(join);
6085 set_current_block(if_false);
6086 } 6022 }
6023 current_block()->GotoNoSimulate(join);
6024 set_current_block(other_map);
6087 } 6025 }
6088 6026
6089 // Deopt if none of the cases matched. 6027 // Deopt if none of the cases matched.
6090 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); 6028 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses);
6091 set_current_block(join); 6029 set_current_block(join);
6092 return is_store ? NULL : Pop(); 6030 return is_store ? NULL : Pop();
6093 } 6031 }
6094 6032
6095 6033
6096 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( 6034 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
(...skipping 4143 matching lines...) Expand 10 before | Expand all | Expand 10 after
10240 if (ShouldProduceTraceOutput()) { 10178 if (ShouldProduceTraceOutput()) {
10241 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 10179 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
10242 } 10180 }
10243 10181
10244 #ifdef DEBUG 10182 #ifdef DEBUG
10245 graph_->Verify(false); // No full verify. 10183 graph_->Verify(false); // No full verify.
10246 #endif 10184 #endif
10247 } 10185 }
10248 10186
10249 } } // namespace v8::internal 10187 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698