hotspot/src/share/vm/utilities/resourceHash.cpp
changeset 41668 e9c6bbf513e5
parent 41667 4a349512fde1
child 41669 2091069b6851
equal deleted inserted replaced
41667:4a349512fde1 41668:e9c6bbf513e5
     1 /*
       
     2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  *
       
    23  */
       
    24 
       
    25 #include "precompiled.hpp"
       
    26 #include "memory/allocation.hpp"
       
    27 #include "memory/resourceArea.hpp"
       
    28 #include "utilities/debug.hpp"
       
    29 #include "utilities/resourceHash.hpp"
       
    30 
       
    31 #ifndef PRODUCT
       
    32 
       
    33 /////////////// Unit tests ///////////////
       
    34 
       
    35 class TestResourceHashtable : public AllStatic {
       
    36   typedef void* K;
       
    37   typedef int V;
       
    38 
       
    39   static unsigned identity_hash(const K& k) {
       
    40     return (unsigned)(uintptr_t)k;
       
    41   }
       
    42 
       
    43   static unsigned bad_hash(const K& k) {
       
    44     return 1;
       
    45   }
       
    46 
       
    47   class EqualityTestIter {
       
    48    public:
       
    49     bool do_entry(K const& k, V const& v) {
       
    50       assert((uintptr_t)k == (uintptr_t)v, "");
       
    51       return true; // continue iteration
       
    52     }
       
    53   };
       
    54 
       
    55   template<
       
    56   unsigned (*HASH)  (K const&)           = primitive_hash<K>,
       
    57   bool     (*EQUALS)(K const&, K const&) = primitive_equals<K>,
       
    58   unsigned SIZE = 256,
       
    59   ResourceObj::allocation_type ALLOC_TYPE = ResourceObj::RESOURCE_AREA,
       
    60   MEMFLAGS MEM_TYPE = mtInternal
       
    61   >
       
    62   class Runner : public AllStatic {
       
    63     static void* as_K(uintptr_t val) { return (void*)val; }
       
    64 
       
    65    public:
       
    66     static void test_small() {
       
    67       EqualityTestIter et;
       
    68       ResourceHashtable<K, V, HASH, EQUALS, SIZE, ALLOC_TYPE, MEM_TYPE> rh;
       
    69 
       
    70       assert(!rh.contains(as_K(0x1)), "");
       
    71 
       
    72       assert(rh.put(as_K(0x1), 0x1), "");
       
    73       assert(rh.contains(as_K(0x1)), "");
       
    74 
       
    75       assert(!rh.put(as_K(0x1), 0x1), "");
       
    76 
       
    77       assert(rh.put(as_K(0x2), 0x2), "");
       
    78       assert(rh.put(as_K(0x3), 0x3), "");
       
    79       assert(rh.put(as_K(0x4), 0x4), "");
       
    80       assert(rh.put(as_K(0x5), 0x5), "");
       
    81 
       
    82       assert(!rh.remove(as_K(0x0)), "");
       
    83       rh.iterate(&et);
       
    84 
       
    85       assert(rh.remove(as_K(0x1)), "");
       
    86       rh.iterate(&et);
       
    87 
       
    88     }
       
    89 
       
    90     // We use keys with the low bits cleared since the default hash will do some shifting
       
    91     static void test_small_shifted() {
       
    92       EqualityTestIter et;
       
    93       ResourceHashtable<K, V, HASH, EQUALS, SIZE, ALLOC_TYPE, MEM_TYPE> rh;
       
    94 
       
    95       assert(!rh.contains(as_K(0x10)), "");
       
    96 
       
    97       assert(rh.put(as_K(0x10), 0x10), "");
       
    98       assert(rh.contains(as_K(0x10)), "");
       
    99 
       
   100       assert(!rh.put(as_K(0x10), 0x10), "");
       
   101 
       
   102       assert(rh.put(as_K(0x20), 0x20), "");
       
   103       assert(rh.put(as_K(0x30), 0x30), "");
       
   104       assert(rh.put(as_K(0x40), 0x40), "");
       
   105       assert(rh.put(as_K(0x50), 0x50), "");
       
   106 
       
   107       assert(!rh.remove(as_K(0x00)), "");
       
   108 
       
   109       assert(rh.remove(as_K(0x10)), "");
       
   110 
       
   111       rh.iterate(&et);
       
   112     }
       
   113 
       
   114     static void test(unsigned num_elements = SIZE) {
       
   115       EqualityTestIter et;
       
   116       ResourceHashtable<K, V, HASH, EQUALS, SIZE, ALLOC_TYPE, MEM_TYPE> rh;
       
   117 
       
   118       for (uintptr_t i = 0; i < num_elements; ++i) {
       
   119         assert(rh.put(as_K(i), i), "");
       
   120       }
       
   121 
       
   122       rh.iterate(&et);
       
   123 
       
   124       for (uintptr_t i = num_elements; i > 0; --i) {
       
   125         uintptr_t index = i - 1;
       
   126         assert(rh.remove(as_K(index)), "");
       
   127       }
       
   128       rh.iterate(&et);
       
   129       for (uintptr_t i = num_elements; i > 0; --i) {
       
   130         uintptr_t index = i - 1;
       
   131         assert(!rh.remove(as_K(index)), "");
       
   132       }
       
   133       rh.iterate(&et);
       
   134     }
       
   135   };
       
   136 
       
   137  public:
       
   138   static void run_tests() {
       
   139     {
       
   140       ResourceMark rm;
       
   141       Runner<>::test_small();
       
   142       Runner<>::test_small_shifted();
       
   143       Runner<>::test();
       
   144     }
       
   145 
       
   146     {
       
   147       ResourceMark rm;
       
   148       Runner<identity_hash>::test_small();
       
   149       Runner<identity_hash>::test_small_shifted();
       
   150       Runner<identity_hash>::test();
       
   151     }
       
   152 
       
   153     {
       
   154       ResourceMark rm;
       
   155       Runner<bad_hash>::test_small();
       
   156       Runner<bad_hash>::test_small_shifted();
       
   157       Runner<bad_hash>::test();
       
   158     }
       
   159 
       
   160 
       
   161     assert(Thread::current()->resource_area()->nesting() == 0, "this code depends on not having an active ResourceMark");
       
   162     // The following test calls will cause an assert if resource allocations occur since we don't have an active mark
       
   163     Runner<primitive_hash<K>, primitive_equals<K>, 512, ResourceObj::C_HEAP>::test_small();
       
   164     Runner<primitive_hash<K>, primitive_equals<K>, 512, ResourceObj::C_HEAP>::test_small_shifted();
       
   165     Runner<primitive_hash<K>, primitive_equals<K>, 512, ResourceObj::C_HEAP>::test();
       
   166 
       
   167     Runner<bad_hash, primitive_equals<K>, 512, ResourceObj::C_HEAP>::test_small();
       
   168     Runner<bad_hash, primitive_equals<K>, 512, ResourceObj::C_HEAP>::test_small_shifted();
       
   169     Runner<bad_hash, primitive_equals<K>, 512, ResourceObj::C_HEAP>::test();
       
   170 
       
   171     Runner<identity_hash, primitive_equals<K>, 1, ResourceObj::C_HEAP>::test_small();
       
   172     Runner<identity_hash, primitive_equals<K>, 1, ResourceObj::C_HEAP>::test_small_shifted();
       
   173     Runner<identity_hash, primitive_equals<K>, 1, ResourceObj::C_HEAP>::test(512);
       
   174   }
       
   175 };
       
   176 
       
   177 void TestResourcehash_test() {
       
   178   TestResourceHashtable::run_tests();
       
   179 }
       
   180 
       
   181 #endif // not PRODUCT
       
   182