OLD | NEW |
---|---|
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 2283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2294 } | 2294 } |
2295 ~NoObservableSideEffectsScope() { | 2295 ~NoObservableSideEffectsScope() { |
2296 builder_->graph()->DecrementInNoSideEffectsScope(); | 2296 builder_->graph()->DecrementInNoSideEffectsScope(); |
2297 } | 2297 } |
2298 | 2298 |
2299 private: | 2299 private: |
2300 HGraphBuilder* builder_; | 2300 HGraphBuilder* builder_; |
2301 }; | 2301 }; |
2302 | 2302 |
2303 | 2303 |
2304 template <typename T> | |
2305 class HUniqueSet; | |
2306 | |
2307 | |
2308 template <typename T> | |
2309 class HUnique V8_FINAL { | |
rossberg
2013/09/11 10:34:07
I think this should live somewhere else (e.g. hand
Toon Verwaest
2013/09/11 11:17:57
A separate file would be nice.
| |
2310 public: | |
2311 // TODO(titzer): this should be private. | |
2312 explicit HUnique(Handle<T> handle) { | |
2313 if (handle.is_null()) { | |
2314 raw_address_ = NULL; | |
2315 } else { | |
2316 raw_address_ = reinterpret_cast<Address>(*handle); | |
Toon Verwaest
2013/09/11 11:17:57
Can we ensure that this is only called in a Disall
| |
2317 ASSERT_NE(raw_address_, NULL); | |
2318 } | |
2319 handle_ = handle; | |
2320 } | |
2321 | |
2322 // Constructor for handling automatic up casting. | |
2323 // Ex. HUnique<JSFunction> can be passed when HUnique<Object> is expected. | |
2324 template <class S> HUnique(HUnique<S> uniq) { | |
2325 #ifdef DEBUG | |
2326 T* a = NULL; | |
2327 S* b = NULL; | |
2328 a = b; // Fake assignment to enforce type checks. | |
2329 USE(a); | |
2330 #endif | |
2331 raw_address_ = uniq.raw_address_; | |
2332 handle_ = uniq.handle_; // Creates a new handle sharing the same location. | |
2333 } | |
2334 | |
2335 template <typename U> | |
2336 bool operator==(const HUnique<U>& other) const { | |
2337 return raw_address_ == other.raw_address_; | |
2338 } | |
2339 | |
2340 template <typename U> | |
2341 bool operator!=(const HUnique<U>& other) const { | |
2342 return raw_address_ != other.raw_address_; | |
2343 } | |
2344 | |
2345 intptr_t Hashcode() const { | |
2346 return reinterpret_cast<intptr_t>(raw_address_); | |
2347 } | |
2348 | |
2349 bool IsNull() { | |
2350 return raw_address_ == NULL; | |
2351 } | |
2352 | |
2353 // Don't do this unless you have access to the heap! | |
2354 // No, seriously! You can compare and hash and set-ify uniques that were | |
2355 // all created at the same time; please don't dereference. | |
2356 Handle<T> handle() { | |
2357 return handle_; | |
2358 } | |
2359 | |
2360 friend class HUniqueSet<T>; // Uses internal implementation details for speed | |
2361 template <class U> | |
2362 friend class HUnique; // For comparing raw_address values | |
2363 | |
2364 private: | |
2365 Address raw_address_; | |
2366 Handle<T> handle_; | |
2367 }; | |
2368 | |
2369 | |
2370 template <typename T> | |
2371 class HUniqueSet V8_FINAL : public ZoneObject { | |
2372 public: | |
2373 // Constructor; a new set will be empty. | |
2374 HUniqueSet() : size_(0), capacity_(0), array_(NULL) { } | |
2375 | |
2376 // Add a new element to this unique set; mutates this set. | |
2377 void Add(HUnique<T> uniq, Zone* zone) { | |
2378 // Keep the set sorted by the {raw_address} of the unique elements. | |
2379 for (int i = 0; i < size_; i++) { | |
2380 if (array_[i] == uniq) return; | |
2381 if (array_[i].raw_address_ > uniq.raw_address_) { | |
2382 // Insert in the middle. | |
2383 Grow(size_ + 1, zone); | |
Toon Verwaest
2013/09/11 11:17:57
You can merge this code with the code after the fo
| |
2384 for (int j = size_ - 1; j >= i; j--) { | |
rossberg
2013/09/11 10:34:07
Could it be worth using memmove here?
| |
2385 array_[j + 1] = array_[j]; | |
2386 } | |
2387 array_[i] = uniq; | |
2388 size_++; | |
2389 return; | |
2390 } | |
2391 } | |
2392 // Append the element to the the end. | |
2393 Grow(size_ + 1, zone); | |
2394 array_[size_++] = uniq; | |
2395 } | |
2396 | |
2397 // Compare this set against another set. | |
2398 bool Equals(HUniqueSet<T>* that) { | |
2399 if (that->size_ != this->size_) return false; | |
2400 for (int i = 0; i < this->size_; i++) { | |
2401 if (this->array_[i] != that->array_[i]) return false; | |
2402 } | |
2403 return true; | |
2404 } | |
2405 | |
2406 // Check if this set is a subset of the given set. | |
2407 bool IsSubset(HUniqueSet<T>* that) { | |
2408 if (that->size_ < this->size_) return false; | |
2409 int j = 0; | |
2410 for (int i = 0; i < this->size_; i++) { | |
2411 HUnique<T> sought = this->array_[i]; | |
2412 bool found = false; | |
rossberg
2013/09/11 10:34:07
The rest of this for-loop could be simplified to:
Toon Verwaest
2013/09/11 14:24:11
This version double-checks every entry though; sin
rossberg
2013/09/11 15:01:49
Good catch. Tweaking that is left as an exercise.
Toon Verwaest
2013/09/11 15:27:53
Hence the version I attached in my previous commen
rossberg
2013/09/12 09:34:45
That's still one for the kitty. :)
| |
2413 while (j < that->size_) { | |
2414 if (sought == that->array_[j++]) { | |
2415 found = true; | |
2416 break; | |
2417 } | |
2418 } | |
2419 if (!found) return false; | |
Toon Verwaest
2013/09/11 11:17:57
For minimal checking
if (that->size_ < this->size
| |
2420 } | |
2421 return true; | |
2422 } | |
2423 | |
2424 // Returns a new set representing the intersection of this set and the other. | |
2425 HUniqueSet<T>* Intersect(HUniqueSet<T>* that, Zone* zone) { | |
2426 if (that->size_ == 0 || this->size_ == 0) return new(zone) HUniqueSet<T>(); | |
2427 | |
2428 HUniqueSet<T>* out = new(zone) HUniqueSet<T>(); | |
2429 out->Grow(this->size_ > that->size_ ? this->size_ : that->size_, zone); | |
rossberg
2013/09/11 10:34:07
Nit: Min(...)
Toon Verwaest
2013/09/11 11:17:57
I guess you meant to flip the sizes?
What about ju
| |
2430 | |
2431 int i = 0, j = 0, k = 0; | |
2432 for (;;) { | |
2433 if (i >= this->size_) break; // Left has been exhausted. | |
2434 if (j >= that->size_) break; // Right has been exhausted. | |
rossberg
2013/09/11 10:34:07
Why not simply
while (i < this->size && j < that-
| |
2435 | |
2436 HUnique<T> a = this->array_[i]; | |
2437 HUnique<T> b = that->array_[j]; | |
2438 if (a == b) { | |
2439 out->array_[k++] = a; | |
2440 i++; | |
2441 j++; | |
2442 } else if (a.raw_address_ < b.raw_address_) { | |
2443 i++; | |
2444 } else { | |
2445 j++; | |
2446 } | |
2447 } | |
2448 | |
2449 out->size_ = k; | |
2450 return out; | |
2451 } | |
2452 | |
2453 // Returns a new set representing the union of this set and the other. | |
2454 HUniqueSet<T>* Union(HUniqueSet<T>* that, Zone* zone) { | |
2455 if (that->size_ == 0) return this->Copy(zone); | |
2456 if (this->size_ == 0) return that->Copy(zone); | |
2457 | |
2458 HUniqueSet<T>* out = new(zone) HUniqueSet<T>(); | |
2459 out->Grow(this->size_ + that->size_, zone); | |
2460 | |
2461 int i = 0, j = 0, k = 0; | |
2462 for (;;) { | |
rossberg
2013/09/11 10:34:07
Same here:
while (i < this->size && j < that->siz
| |
2463 if (i >= this->size_) { // Left has been exhausted. | |
2464 while (j < that->size_) out->array_[k++] = that->array_[j++]; | |
2465 break; | |
2466 } | |
2467 if (j >= that->size_) { // Right has been exhausted. | |
2468 while (i < this->size_) out->array_[k++] = this->array_[i++]; | |
2469 break; | |
2470 } | |
2471 | |
2472 HUnique<T> a = this->array_[i]; | |
2473 HUnique<T> b = that->array_[j]; | |
2474 if (a == b) { | |
2475 out->array_[k++] = a; | |
2476 i++; | |
2477 j++; | |
2478 } else if (a.raw_address_ < b.raw_address_) { | |
2479 out->array_[k++] = a; | |
2480 i++; | |
2481 } else { | |
2482 out->array_[k++] = b; | |
2483 j++; | |
2484 } | |
2485 } | |
2486 | |
2487 out->size_ = k; | |
2488 return out; | |
2489 } | |
2490 | |
2491 // Makes an exact copy of this set. | |
2492 HUniqueSet<T>* Copy(Zone* zone) { | |
2493 HUniqueSet<T>* copy = new(zone) HUniqueSet<T>(); | |
2494 copy->size_ = this->size_; | |
2495 copy->capacity_ = this->size_; | |
2496 copy->array_ = zone->NewArray<HUnique<T> >(this->size_); | |
2497 memcpy(copy->array_, this->array_, this->size_ * sizeof(HUnique<T>)); | |
2498 return copy; | |
2499 } | |
2500 | |
2501 inline int size() { | |
2502 return size_; | |
2503 } | |
2504 | |
2505 private: | |
2506 // These sets should be small, since operations are implemented with simple | |
2507 // linear algorithms. Enforce a maximum size. | |
2508 static const int kMaxCapacity = 65535; | |
2509 | |
2510 uint16_t size_; | |
2511 uint16_t capacity_; | |
2512 HUnique<T>* array_; | |
2513 | |
2514 // Grow the size of internal storage to be at least {size} elements. | |
2515 void Grow(int size, Zone* zone) { | |
2516 CHECK(size < kMaxCapacity); // Enforce maximum size. | |
2517 if (capacity_ < size) { | |
2518 int new_capacity = capacity_ + capacity_ + size; // 2*current + needed | |
rossberg
2013/09/11 10:34:07
That seems like a lot, and can cause up to a 200%
Toon Verwaest
2013/09/11 11:17:57
I guess this is 0, 1 or 4? Otherwise it seems like
| |
2519 if (new_capacity > kMaxCapacity) new_capacity = kMaxCapacity; | |
2520 HUnique<T>* new_array = zone->NewArray<HUnique<T> >(new_capacity); | |
2521 memcpy(new_array, array_, size_ * sizeof(HUnique<T>)); | |
2522 capacity_ = new_capacity; | |
2523 array_ = new_array; | |
2524 } | |
2525 } | |
2526 }; | |
2527 | |
2528 | |
2304 } } // namespace v8::internal | 2529 } } // namespace v8::internal |
2305 | 2530 |
2306 #endif // V8_HYDROGEN_H_ | 2531 #endif // V8_HYDROGEN_H_ |
OLD | NEW |