1 /*
2  * Copyright (c) 2020, 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 #include "precompiled.hpp"
25 #include "classfile/symbolTable.hpp"
26 #include "memory/resourceArea.hpp"
27 #include "runtime/interfaceSupport.inline.hpp"
28 #include "runtime/signature.hpp"
29 #include "threadHelper.inline.hpp"
30 #include "unittest.hpp"
31 
TEST_VM(SignatureStream,check_refcount)32 TEST_VM(SignatureStream, check_refcount) {
33 
34   JavaThread* THREAD = JavaThread::current();
35   // the thread should be in vm to use locks
36   ThreadInVMfromNative ThreadInVMfromNative(THREAD);
37   // SignatureStream::as_symbol will allocate on the resource area
38   ResourceMark rm(THREAD);
39 
40   Symbol* foo = SymbolTable::new_symbol("Foo");
41   int r1 = foo->refcount();
42 
43   {
44     // Trivial test: non-method signature of a non-permanent symbol
45     Symbol* methodSig = SymbolTable::new_symbol("LFoo;");
46     SignatureStream ss(methodSig, false);
47     Symbol* sym = ss.as_symbol();
48     ASSERT_EQ(sym, foo) << "found symbol should be Foo: " << sym->as_C_string();
49     // This should mean the SS looks up and increments refcount to Foo
50     ASSERT_EQ(foo->refcount(), r1 + 1) << "refcount should be incremented";
51 
52     ASSERT_TRUE(!ss.is_done())
53       << "stream parsing should not be marked as done until"
54       <<" ss.next() called after the last symbol";
55 
56     ss.next();
57     ASSERT_TRUE(ss.is_done()) << "stream parsing should be marked as done";
58   }
59 
60   ASSERT_EQ(foo->refcount(), r1) << "refcount should have decremented";
61 
62   {
63     // Ensure refcount is properly decremented when first symbol is non-permanent and second isn't
64 
65     Symbol* integer = SymbolTable::new_symbol("java/lang/Integer");
66     ASSERT_TRUE(integer->is_permanent()) << "java/lang/Integer must be permanent";
67 
68     Symbol* methodSig = SymbolTable::new_symbol("(LFoo;)Ljava/lang/Integer;");
69     SignatureStream ss(methodSig);
70     Symbol* sym = ss.as_symbol();
71     ASSERT_EQ(sym, foo) << "found symbol should be Foo: " << sym->as_C_string();
72     // This should mean the SS looks up and increments refcount to Foo
73     ASSERT_EQ(foo->refcount(), r1 + 1) << "refcount should be incremented";
74 
75     ss.next();
76     sym = ss.as_symbol();
77     ASSERT_EQ(sym, integer) << "found symbol should be java/lang/Integer";
78 
79     ASSERT_TRUE(!ss.is_done())
80       << "stream parsing should not be marked as done until"
81       <<" ss.next() called after the last symbol";
82 
83     ss.next();
84     ASSERT_TRUE(ss.is_done()) << "stream parsing should be marked as done";
85   }
86 
87   ASSERT_EQ(foo->refcount(), r1) << "refcount should have decremented";
88 
89 }
90