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

Side by Side Diff: src/objects.cc

Issue 9226017: Sketch for TraverseTransitionTree. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 11 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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 4917 matching lines...) Expand 10 before | Expand all | Expand 10 after
4928 4928
4929 4929
4930 void Map::RemoveFromCodeCache(String* name, Code* code, int index) { 4930 void Map::RemoveFromCodeCache(String* name, Code* code, int index) {
4931 // No GC is supposed to happen between a call to IndexInCodeCache and 4931 // No GC is supposed to happen between a call to IndexInCodeCache and
4932 // RemoveFromCodeCache so the code cache must be there. 4932 // RemoveFromCodeCache so the code cache must be there.
4933 ASSERT(!code_cache()->IsFixedArray()); 4933 ASSERT(!code_cache()->IsFixedArray());
4934 CodeCache::cast(code_cache())->RemoveByIndex(name, code, index); 4934 CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
4935 } 4935 }
4936 4936
4937 4937
4938 class IntrusiveIterationState {
4939 public:
4940 IntrusiveIterationState(HeapObject* obj)
4941 : obj_(obj) { }
4942
4943 Object* Get() {
4944 return *HeapObject::RawField(obj_, HeapObject::kMapOffset);
4945 }
4946
4947 void Set(Object* s) {
4948 *HeapObject::RawField(obj_, HeapObject::kMapOffset) = s;
4949 }
4950
4951 private:
4952 HeapObject* obj_;
4953 };
4954
4955
4956 class IntrusiveFixedArrayIterator {
4957 public:
4958 IntrusiveFixedArrayIterator(FixedArray* array)
4959 : state_(array) { }
4960
4961 bool IsIterating() {
4962 return state_.Get()->IsSmi();
4963 }
4964
4965 int GetIndex() {
4966 return Smi::cast(state_.Get())->value();
4967 }
4968
4969 void SetIndex(int index) {
4970 state_.Set(Smi::FromInt(index));
4971 }
4972
4973 void Stop() {
4974 state_.Set(HEAP->fixed_array_map());
4975 }
4976
4977 private:
4978 IntrusiveIterationState state_;
4979 };
4980
4981
4982 class IntrusiveMapIterator {
4983 public:
4984 IntrusiveMapIterator(Map* map)
4985 : current_(map) { }
4986
4987 void DescendInto(Map* child) {
4988 Map* parent = Current();
4989 SetCurrent(child);
4990 ASSERT(Parent() == HEAP->meta_map());
4991 SetParent(parent);
4992 }
4993
4994 Map* Ascend() {
4995 // We are done with the current map.
4996 // Before ascending reset iteration state.
4997 StopMapTransitionsIteration();
4998 StopPrototypeTransitionsIteration();
4999
5000 Map* parent = Parent();
5001 SetParent(HEAP->meta_map());
5002
5003 Map* current = Current();
5004 SetCurrent(parent);
5005
5006 return current;
5007 }
5008
5009 bool HasMore() {
5010 return Current() != HEAP->meta_map();
5011 }
5012
5013
5014 Map* NextUnvisitedChild() {
5015 Map* child = NULL;
5016
5017 child = NextUnvisitedMapTransition();
5018 if (child != NULL) return child;
5019
5020 child = NextUnvisitedPrototypeTransition();
5021 if (child != NULL) return child;
5022
5023 return NULL;
5024 }
5025
5026 private:
5027 Map* current_;
5028
5029 Map* Current() {
5030 return current_;
5031 }
5032
5033 void SetCurrent(Map* current) {
5034 current_ = current;
5035 }
5036
5037 Map* Parent() {
5038 return reinterpret_cast<Map*>(IntrusiveIterationState(current_).Get());
5039 }
5040
5041 void SetParent(Map* parent) {
5042 IntrusiveIterationState(current_).Set(parent);
5043 }
5044
5045 FixedArray* ContentArray() {
5046 DescriptorArray* d = Current()->instance_descriptors();
5047 return reinterpret_cast<FixedArray*>(
5048 d->get(DescriptorArray::kContentArrayIndex));
5049 }
5050
5051 bool HasContentArray() {
5052 return !Current()->instance_descriptors()->IsEmpty();
5053 }
5054
5055 void StopMapTransitionsIteration() {
5056 if (HasContentArray()) {
5057 IntrusiveFixedArrayIterator it(ContentArray());
5058 it.Stop();
5059 }
5060 }
5061
5062 Map* NextUnvisitedMapTransition() {
5063 if (HasContentArray()) {
5064 FixedArray* content = ContentArray();
5065
5066 IntrusiveFixedArrayIterator it(content);
5067 for (int i = it.IsIterating() ? it.GetIndex() : 0;
5068 i < content->length();
5069 i += 2) {
5070 PropertyDetails details(Smi::cast(content->get(i + 1)));
5071 if (details.IsTransition()) {
5072 // Found a map in the transition array. We record our progress in
5073 // the transition array by recording the current map in the map field
5074 // of the next map and recording the index in the transition array in
5075 // the map field of the array.
5076 Map* child = Map::cast(content->get(i));
5077 it.SetIndex(i + 2);
5078 return child;
5079 }
5080 }
5081 }
5082 return NULL;
5083 }
5084
5085 void StopPrototypeTransitionsIteration() {
5086 FixedArray* array = Current()->unchecked_prototype_transitions();
5087 IntrusiveFixedArrayIterator it(array);
5088 it.Stop();
5089 }
5090
5091 Map* NextUnvisitedPrototypeTransition() {
5092 FixedArray* array = Current()->unchecked_prototype_transitions();
5093 IntrusiveFixedArrayIterator it(array);
5094
5095 static const int kFirstMapIndex =
5096 (Map::kProtoTransitionHeaderSize + Map::kProtoTransitionMapOffset);
5097
5098 int index = it.IsIterating() ? it.GetIndex() : kFirstMapIndex;
5099
5100 if (index < array->length()) {
5101 Object* child = array->get(index);
5102 if (child->IsMap()) {
5103 it.SetIndex(index + Map::kProtoTransitionElementsPerEntry);
5104 return Map::cast(child);
5105 }
5106 }
5107
5108 return NULL;
5109 }
5110 };
5111
5112
4938 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) { 5113 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
4939 // Traverse the transition tree without using a stack. We do this by 5114 // Traverse the transition tree without using a stack. We do this by
4940 // reversing the pointers in the maps and descriptor arrays. 5115 // reversing the pointers in the maps and descriptor arrays.
4941 Map* current = this; 5116 IntrusiveMapIterator it(this);
4942 Map* meta_map = GetHeap()->meta_map(); 5117 while (it.HasMore()) {
4943 Object** map_or_index_field = NULL; 5118 Map* child = it.NextUnvisitedChild();
4944 while (current != meta_map) { 5119 if (child != NULL) {
4945 DescriptorArray* d = reinterpret_cast<DescriptorArray*>( 5120 it.DescendInto(child);
4946 *RawField(current, Map::kInstanceDescriptorsOrBitField3Offset));
4947 if (!d->IsEmpty()) {
4948 FixedArray* contents = reinterpret_cast<FixedArray*>(
4949 d->get(DescriptorArray::kContentArrayIndex));
4950 map_or_index_field = RawField(contents, HeapObject::kMapOffset);
4951 Object* map_or_index = *map_or_index_field;
4952 bool map_done = true; // Controls a nested continue statement.
4953 for (int i = map_or_index->IsSmi() ? Smi::cast(map_or_index)->value() : 0;
4954 i < contents->length();
4955 i += 2) {
4956 PropertyDetails details(Smi::cast(contents->get(i + 1)));
4957 if (details.IsTransition()) {
4958 // Found a map in the transition array. We record our progress in
4959 // the transition array by recording the current map in the map field
4960 // of the next map and recording the index in the transition array in
4961 // the map field of the array.
4962 Map* next = Map::cast(contents->get(i));
4963 next->set_map_no_write_barrier(current);
4964 *map_or_index_field = Smi::FromInt(i + 2);
4965 current = next;
4966 map_done = false;
4967 break;
4968 }
4969 }
4970 if (!map_done) continue;
4971 } else { 5121 } else {
4972 map_or_index_field = NULL; 5122 Map* map = it.Ascend();
5123 callback(map, data);
4973 } 5124 }
4974 // That was the regular transitions, now for the prototype transitions.
4975 FixedArray* prototype_transitions =
4976 current->unchecked_prototype_transitions();
4977 Object** proto_map_or_index_field =
4978 RawField(prototype_transitions, HeapObject::kMapOffset);
4979 Object* map_or_index = *proto_map_or_index_field;
4980 const int start = kProtoTransitionHeaderSize + kProtoTransitionMapOffset;
4981 int i = map_or_index->IsSmi() ? Smi::cast(map_or_index)->value() : start;
4982 if (i < prototype_transitions->length()) {
4983 // Found a map in the prototype transition array. Record progress in
4984 // an analogous way to the regular transitions array above.
4985 Object* perhaps_map = prototype_transitions->get(i);
4986 if (perhaps_map->IsMap()) {
4987 Map* next = Map::cast(perhaps_map);
4988 next->set_map_no_write_barrier(current);
4989 *proto_map_or_index_field =
4990 Smi::FromInt(i + kProtoTransitionElementsPerEntry);
4991 current = next;
4992 continue;
4993 }
4994 }
4995 *proto_map_or_index_field = GetHeap()->fixed_array_map();
4996 if (map_or_index_field != NULL) {
4997 *map_or_index_field = GetHeap()->fixed_array_map();
4998 }
4999
5000 // The callback expects a map to have a real map as its map, so we save
5001 // the map field, which is being used to track the traversal and put the
5002 // correct map (the meta_map) in place while we do the callback.
5003 Map* prev = current->map();
5004 current->set_map_no_write_barrier(meta_map);
5005 callback(current, data);
5006 current = prev;
5007 } 5125 }
5008 } 5126 }
5009 5127
5010 5128
5011 MaybeObject* CodeCache::Update(String* name, Code* code) { 5129 MaybeObject* CodeCache::Update(String* name, Code* code) {
5012 // The number of monomorphic stubs for normal load/store/call IC's can grow to 5130 // The number of monomorphic stubs for normal load/store/call IC's can grow to
5013 // a large number and therefore they need to go into a hash table. They are 5131 // a large number and therefore they need to go into a hash table. They are
5014 // used to load global properties from cells. 5132 // used to load global properties from cells.
5015 if (code->type() == NORMAL) { 5133 if (code->type() == NORMAL) {
5016 // Make sure that a hash table is allocated for the normal load code cache. 5134 // Make sure that a hash table is allocated for the normal load code cache.
(...skipping 7792 matching lines...) Expand 10 before | Expand all | Expand 10 after
12809 if (break_point_objects()->IsUndefined()) return 0; 12927 if (break_point_objects()->IsUndefined()) return 0;
12810 // Single break point. 12928 // Single break point.
12811 if (!break_point_objects()->IsFixedArray()) return 1; 12929 if (!break_point_objects()->IsFixedArray()) return 1;
12812 // Multiple break points. 12930 // Multiple break points.
12813 return FixedArray::cast(break_point_objects())->length(); 12931 return FixedArray::cast(break_point_objects())->length();
12814 } 12932 }
12815 #endif // ENABLE_DEBUGGER_SUPPORT 12933 #endif // ENABLE_DEBUGGER_SUPPORT
12816 12934
12817 12935
12818 } } // namespace v8::internal 12936 } } // 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