Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 5128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5139 set(EntryToIndex(index) + 1, heap->null_value()); | 5139 set(EntryToIndex(index) + 1, heap->null_value()); |
| 5140 ElementRemoved(); | 5140 ElementRemoved(); |
| 5141 } | 5141 } |
| 5142 | 5142 |
| 5143 | 5143 |
| 5144 void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> cache, | 5144 void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> cache, |
| 5145 MapHandleList* maps, | 5145 MapHandleList* maps, |
| 5146 Code::Flags flags, | 5146 Code::Flags flags, |
| 5147 Handle<Code> code) { | 5147 Handle<Code> code) { |
| 5148 Isolate* isolate = cache->GetIsolate(); | 5148 Isolate* isolate = cache->GetIsolate(); |
| 5149 List<Map*> raw_maps(maps->length()); | 5149 CALL_HEAP_FUNCTION_VOID(isolate, cache->Update(maps, flags, *code)); |
| 5150 CALL_HEAP_FUNCTION_VOID( | |
| 5151 isolate, | |
| 5152 (raw_maps.Clear(), | |
| 5153 cache->Update(UnwrapHandleList(&raw_maps, maps), flags, *code))); | |
| 5154 } | 5150 } |
| 5155 | 5151 |
| 5156 | 5152 |
| 5157 MaybeObject* PolymorphicCodeCache::Update(MapList* maps, | 5153 MaybeObject* PolymorphicCodeCache::Update(MapHandleList* maps, |
| 5158 Code::Flags flags, | 5154 Code::Flags flags, |
| 5159 Code* code) { | 5155 Code* code) { |
| 5160 // Initialize cache if necessary. | 5156 // Initialize cache if necessary. |
| 5161 if (cache()->IsUndefined()) { | 5157 if (cache()->IsUndefined()) { |
| 5162 Object* result; | 5158 Object* result; |
| 5163 { MaybeObject* maybe_result = | 5159 { MaybeObject* maybe_result = |
| 5164 PolymorphicCodeCacheHashTable::Allocate( | 5160 PolymorphicCodeCacheHashTable::Allocate( |
| 5165 PolymorphicCodeCacheHashTable::kInitialSize); | 5161 PolymorphicCodeCacheHashTable::kInitialSize); |
| 5166 if (!maybe_result->ToObject(&result)) return maybe_result; | 5162 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 5167 } | 5163 } |
| 5168 set_cache(result); | 5164 set_cache(result); |
| 5169 } else { | 5165 } else { |
| 5170 // This entry shouldn't be contained in the cache yet. | 5166 // This entry shouldn't be contained in the cache yet. |
| 5171 ASSERT(PolymorphicCodeCacheHashTable::cast(cache()) | 5167 ASSERT(PolymorphicCodeCacheHashTable::cast(cache()) |
| 5172 ->Lookup(maps, flags)->IsUndefined()); | 5168 ->Lookup(maps, flags)->IsUndefined()); |
| 5173 } | 5169 } |
| 5174 PolymorphicCodeCacheHashTable* hash_table = | 5170 PolymorphicCodeCacheHashTable* hash_table = |
| 5175 PolymorphicCodeCacheHashTable::cast(cache()); | 5171 PolymorphicCodeCacheHashTable::cast(cache()); |
| 5176 Object* new_cache; | 5172 Object* new_cache; |
| 5177 { MaybeObject* maybe_new_cache = hash_table->Put(maps, flags, code); | 5173 { MaybeObject* maybe_new_cache = hash_table->Put(maps, flags, code); |
| 5178 if (!maybe_new_cache->ToObject(&new_cache)) return maybe_new_cache; | 5174 if (!maybe_new_cache->ToObject(&new_cache)) return maybe_new_cache; |
| 5179 } | 5175 } |
| 5180 set_cache(new_cache); | 5176 set_cache(new_cache); |
| 5181 return this; | 5177 return this; |
| 5182 } | 5178 } |
| 5183 | 5179 |
| 5184 | 5180 |
| 5185 Handle<Object> PolymorphicCodeCache::Lookup(MapHandleList* maps, | 5181 Handle<Object> PolymorphicCodeCache::Lookup(MapHandleList* maps, |
| 5186 Code::Flags flags) { | 5182 Code::Flags flags) { |
| 5187 List<Map*> raw_maps(maps->length()); | |
| 5188 return Handle<Object>(Lookup(UnwrapHandleList(&raw_maps, maps), flags)); | |
| 5189 } | |
| 5190 | |
| 5191 | |
| 5192 Object* PolymorphicCodeCache::Lookup(MapList* maps, Code::Flags flags) { | |
| 5193 if (!cache()->IsUndefined()) { | 5183 if (!cache()->IsUndefined()) { |
| 5194 PolymorphicCodeCacheHashTable* hash_table = | 5184 PolymorphicCodeCacheHashTable* hash_table = |
| 5195 PolymorphicCodeCacheHashTable::cast(cache()); | 5185 PolymorphicCodeCacheHashTable::cast(cache()); |
| 5196 return hash_table->Lookup(maps, flags); | 5186 return Handle<Object>(hash_table->Lookup(maps, flags)); |
| 5197 } else { | 5187 } else { |
| 5198 return GetHeap()->undefined_value(); | 5188 return GetIsolate()->factory()->undefined_value(); |
| 5199 } | 5189 } |
| 5200 } | 5190 } |
| 5201 | 5191 |
| 5202 | 5192 |
| 5203 // Despite their name, object of this class are not stored in the actual | 5193 // Despite their name, object of this class are not stored in the actual |
| 5204 // hash table; instead they're temporarily used for lookups. It is therefore | 5194 // hash table; instead they're temporarily used for lookups. It is therefore |
| 5205 // safe to have a weak (non-owning) pointer to a MapList as a member field. | 5195 // safe to have a weak (non-owning) pointer to a MapList as a member field. |
| 5206 class PolymorphicCodeCacheHashTableKey : public HashTableKey { | 5196 class PolymorphicCodeCacheHashTableKey : public HashTableKey { |
| 5207 public: | 5197 public: |
| 5208 // Callers must ensure that |maps| outlives the newly constructed object. | 5198 // Callers must ensure that |maps| outlives the newly constructed object. |
| 5209 PolymorphicCodeCacheHashTableKey(MapList* maps, int code_flags) | 5199 PolymorphicCodeCacheHashTableKey(MapHandleList* maps, int code_flags) |
| 5210 : maps_(maps), | 5200 : maps_(maps), |
| 5211 code_flags_(code_flags) {} | 5201 code_flags_(code_flags) {} |
| 5212 | 5202 |
| 5213 bool IsMatch(Object* other) { | 5203 bool IsMatch(Object* other) { |
| 5214 MapList other_maps(kDefaultListAllocationSize); | 5204 MapHandleList other_maps(kDefaultListAllocationSize); |
|
ulan
2011/10/24 09:04:01
Adds new precondition (handle scope) for IsMatch.
| |
| 5215 int other_flags; | 5205 int other_flags; |
| 5216 FromObject(other, &other_flags, &other_maps); | 5206 FromObject(other, &other_flags, &other_maps); |
| 5217 if (code_flags_ != other_flags) return false; | 5207 if (code_flags_ != other_flags) return false; |
| 5218 if (maps_->length() != other_maps.length()) return false; | 5208 if (maps_->length() != other_maps.length()) return false; |
| 5219 // Compare just the hashes first because it's faster. | 5209 // Compare just the hashes first because it's faster. |
| 5220 int this_hash = MapsHashHelper(maps_, code_flags_); | 5210 int this_hash = MapsHashHelper(maps_, code_flags_); |
| 5221 int other_hash = MapsHashHelper(&other_maps, other_flags); | 5211 int other_hash = MapsHashHelper(&other_maps, other_flags); |
| 5222 if (this_hash != other_hash) return false; | 5212 if (this_hash != other_hash) return false; |
| 5223 | 5213 |
| 5224 // Full comparison: for each map in maps_, look for an equivalent map in | 5214 // Full comparison: for each map in maps_, look for an equivalent map in |
| 5225 // other_maps. This implementation is slow, but probably good enough for | 5215 // other_maps. This implementation is slow, but probably good enough for |
| 5226 // now because the lists are short (<= 4 elements currently). | 5216 // now because the lists are short (<= 4 elements currently). |
| 5227 for (int i = 0; i < maps_->length(); ++i) { | 5217 for (int i = 0; i < maps_->length(); ++i) { |
| 5228 bool match_found = false; | 5218 bool match_found = false; |
| 5229 for (int j = 0; j < other_maps.length(); ++j) { | 5219 for (int j = 0; j < other_maps.length(); ++j) { |
| 5230 if (maps_->at(i)->EquivalentTo(other_maps.at(j))) { | 5220 if (maps_->at(i)->EquivalentTo(*other_maps.at(j))) { |
| 5231 match_found = true; | 5221 match_found = true; |
| 5232 break; | 5222 break; |
| 5233 } | 5223 } |
| 5234 } | 5224 } |
| 5235 if (!match_found) return false; | 5225 if (!match_found) return false; |
| 5236 } | 5226 } |
| 5237 return true; | 5227 return true; |
| 5238 } | 5228 } |
| 5239 | 5229 |
| 5240 static uint32_t MapsHashHelper(MapList* maps, int code_flags) { | 5230 static uint32_t MapsHashHelper(MapHandleList* maps, int code_flags) { |
| 5241 uint32_t hash = code_flags; | 5231 uint32_t hash = code_flags; |
| 5242 for (int i = 0; i < maps->length(); ++i) { | 5232 for (int i = 0; i < maps->length(); ++i) { |
| 5243 hash ^= maps->at(i)->Hash(); | 5233 hash ^= maps->at(i)->Hash(); |
| 5244 } | 5234 } |
| 5245 return hash; | 5235 return hash; |
| 5246 } | 5236 } |
| 5247 | 5237 |
| 5248 uint32_t Hash() { | 5238 uint32_t Hash() { |
| 5249 return MapsHashHelper(maps_, code_flags_); | 5239 return MapsHashHelper(maps_, code_flags_); |
| 5250 } | 5240 } |
| 5251 | 5241 |
| 5252 uint32_t HashForObject(Object* obj) { | 5242 uint32_t HashForObject(Object* obj) { |
| 5253 MapList other_maps(kDefaultListAllocationSize); | 5243 MapHandleList other_maps(kDefaultListAllocationSize); |
|
ulan
2011/10/24 09:04:01
Adds new precondition (handle scope) for HashForOb
| |
| 5254 int other_flags; | 5244 int other_flags; |
| 5255 FromObject(obj, &other_flags, &other_maps); | 5245 FromObject(obj, &other_flags, &other_maps); |
| 5256 return MapsHashHelper(&other_maps, other_flags); | 5246 return MapsHashHelper(&other_maps, other_flags); |
| 5257 } | 5247 } |
| 5258 | 5248 |
| 5259 MUST_USE_RESULT MaybeObject* AsObject() { | 5249 MUST_USE_RESULT MaybeObject* AsObject() { |
| 5260 Object* obj; | 5250 Object* obj; |
| 5261 // The maps in |maps_| must be copied to a newly allocated FixedArray, | 5251 // The maps in |maps_| must be copied to a newly allocated FixedArray, |
| 5262 // both because the referenced MapList is short-lived, and because C++ | 5252 // both because the referenced MapList is short-lived, and because C++ |
| 5263 // objects can't be stored in the heap anyway. | 5253 // objects can't be stored in the heap anyway. |
| 5264 { MaybeObject* maybe_obj = | 5254 { MaybeObject* maybe_obj = |
| 5265 HEAP->AllocateUninitializedFixedArray(maps_->length() + 1); | 5255 HEAP->AllocateUninitializedFixedArray(maps_->length() + 1); |
| 5266 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 5256 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 5267 } | 5257 } |
| 5268 FixedArray* list = FixedArray::cast(obj); | 5258 FixedArray* list = FixedArray::cast(obj); |
| 5269 list->set(0, Smi::FromInt(code_flags_)); | 5259 list->set(0, Smi::FromInt(code_flags_)); |
| 5270 for (int i = 0; i < maps_->length(); ++i) { | 5260 for (int i = 0; i < maps_->length(); ++i) { |
| 5271 list->set(i + 1, maps_->at(i)); | 5261 list->set(i + 1, *maps_->at(i)); |
| 5272 } | 5262 } |
| 5273 return list; | 5263 return list; |
| 5274 } | 5264 } |
| 5275 | 5265 |
| 5276 private: | 5266 private: |
| 5277 static MapList* FromObject(Object* obj, int* code_flags, MapList* maps) { | 5267 static MapHandleList* FromObject(Object* obj, |
| 5268 int* code_flags, | |
| 5269 MapHandleList* maps) { | |
| 5278 FixedArray* list = FixedArray::cast(obj); | 5270 FixedArray* list = FixedArray::cast(obj); |
| 5279 maps->Rewind(0); | 5271 maps->Rewind(0); |
| 5280 *code_flags = Smi::cast(list->get(0))->value(); | 5272 *code_flags = Smi::cast(list->get(0))->value(); |
| 5281 for (int i = 1; i < list->length(); ++i) { | 5273 for (int i = 1; i < list->length(); ++i) { |
| 5282 maps->Add(Map::cast(list->get(i))); | 5274 maps->Add(Handle<Map>(Map::cast(list->get(i)))); |
| 5283 } | 5275 } |
| 5284 return maps; | 5276 return maps; |
| 5285 } | 5277 } |
| 5286 | 5278 |
| 5287 MapList* maps_; // weak. | 5279 MapHandleList* maps_; // weak. |
| 5288 int code_flags_; | 5280 int code_flags_; |
| 5289 static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1; | 5281 static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1; |
| 5290 }; | 5282 }; |
| 5291 | 5283 |
| 5292 | 5284 |
| 5293 Object* PolymorphicCodeCacheHashTable::Lookup(MapList* maps, int code_flags) { | 5285 Object* PolymorphicCodeCacheHashTable::Lookup(MapHandleList* maps, |
| 5286 int code_flags) { | |
| 5294 PolymorphicCodeCacheHashTableKey key(maps, code_flags); | 5287 PolymorphicCodeCacheHashTableKey key(maps, code_flags); |
| 5295 int entry = FindEntry(&key); | 5288 int entry = FindEntry(&key); |
| 5296 if (entry == kNotFound) return GetHeap()->undefined_value(); | 5289 if (entry == kNotFound) return GetHeap()->undefined_value(); |
| 5297 return get(EntryToIndex(entry) + 1); | 5290 return get(EntryToIndex(entry) + 1); |
| 5298 } | 5291 } |
| 5299 | 5292 |
| 5300 | 5293 |
| 5301 MaybeObject* PolymorphicCodeCacheHashTable::Put(MapList* maps, | 5294 MaybeObject* PolymorphicCodeCacheHashTable::Put(MapHandleList* maps, |
| 5302 int code_flags, | 5295 int code_flags, |
| 5303 Code* code) { | 5296 Code* code) { |
| 5304 PolymorphicCodeCacheHashTableKey key(maps, code_flags); | 5297 PolymorphicCodeCacheHashTableKey key(maps, code_flags); |
| 5305 Object* obj; | 5298 Object* obj; |
| 5306 { MaybeObject* maybe_obj = EnsureCapacity(1, &key); | 5299 { MaybeObject* maybe_obj = EnsureCapacity(1, &key); |
| 5307 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 5300 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 5308 } | 5301 } |
| 5309 PolymorphicCodeCacheHashTable* cache = | 5302 PolymorphicCodeCacheHashTable* cache = |
| 5310 reinterpret_cast<PolymorphicCodeCacheHashTable*>(obj); | 5303 reinterpret_cast<PolymorphicCodeCacheHashTable*>(obj); |
| 5311 int entry = cache->FindInsertionEntry(key.Hash()); | 5304 int entry = cache->FindInsertionEntry(key.Hash()); |
| (...skipping 7322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12634 if (break_point_objects()->IsUndefined()) return 0; | 12627 if (break_point_objects()->IsUndefined()) return 0; |
| 12635 // Single break point. | 12628 // Single break point. |
| 12636 if (!break_point_objects()->IsFixedArray()) return 1; | 12629 if (!break_point_objects()->IsFixedArray()) return 1; |
| 12637 // Multiple break points. | 12630 // Multiple break points. |
| 12638 return FixedArray::cast(break_point_objects())->length(); | 12631 return FixedArray::cast(break_point_objects())->length(); |
| 12639 } | 12632 } |
| 12640 #endif // ENABLE_DEBUGGER_SUPPORT | 12633 #endif // ENABLE_DEBUGGER_SUPPORT |
| 12641 | 12634 |
| 12642 | 12635 |
| 12643 } } // namespace v8::internal | 12636 } } // namespace v8::internal |
| OLD | NEW |