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 
25 #ifndef SHARE_OPTO_CONSTANTTABLE_HPP
26 #define SHARE_OPTO_CONSTANTTABLE_HPP
27 
28 #include "utilities/globalDefinitions.hpp"
29 
30 class CodeBuffer;
31 class Metadata;
32 class MachConstantNode;
33 class MachOper;
34 
35 class ConstantTable {
36 public:
37   // Constant entry of the constant table.
38   class Constant {
39   private:
40     BasicType _type;
41     union {
42       jvalue    _value;
43       Metadata* _metadata;
44     } _v;
45     int       _offset;         // offset of this constant (in bytes) relative to the constant table base.
46     float     _freq;
47     bool      _can_be_reused;  // true (default) if the value can be shared with other users.
48 
49   public:
Constant()50     Constant() : _type(T_ILLEGAL), _offset(-1), _freq(0.0f), _can_be_reused(true) { _v._value.l = 0; }
Constant(BasicType type,jvalue value,float freq=0.0f,bool can_be_reused=true)51     Constant(BasicType type, jvalue value, float freq = 0.0f, bool can_be_reused = true) :
52       _type(type),
53       _offset(-1),
54       _freq(freq),
55       _can_be_reused(can_be_reused)
56     {
57       assert(type != T_METADATA, "wrong constructor");
58       _v._value = value;
59     }
Constant(Metadata * metadata,bool can_be_reused=true)60     Constant(Metadata* metadata, bool can_be_reused = true) :
61       _type(T_METADATA),
62       _offset(-1),
63       _freq(0.0f),
64       _can_be_reused(can_be_reused)
65     {
66       _v._metadata = metadata;
67     }
68 
69     bool operator==(const Constant& other);
70 
type() const71     BasicType type()      const    { return _type; }
72 
get_jint() const73     jint    get_jint()    const    { return _v._value.i; }
get_jlong() const74     jlong   get_jlong()   const    { return _v._value.j; }
get_jfloat() const75     jfloat  get_jfloat()  const    { return _v._value.f; }
get_jdouble() const76     jdouble get_jdouble() const    { return _v._value.d; }
get_jobject() const77     jobject get_jobject() const    { return _v._value.l; }
78 
get_metadata() const79     Metadata* get_metadata() const { return _v._metadata; }
80 
offset() const81     int         offset()  const    { return _offset; }
set_offset(int offset)82     void    set_offset(int offset) {        _offset = offset; }
83 
freq() const84     float       freq()    const    { return _freq;         }
inc_freq(float freq)85     void    inc_freq(float freq)   {        _freq += freq; }
86 
can_be_reused() const87     bool    can_be_reused() const  { return _can_be_reused; }
88   };
89 
90 private:
91   GrowableArray<Constant> _constants;          // Constants of this table.
92   int                     _size;               // Size in bytes the emitted constant table takes (including padding).
93   int                     _table_base_offset;  // Offset of the table base that gets added to the constant offsets.
94   int                     _nof_jump_tables;    // Number of jump-tables in this constant table.
95 
96   static int qsort_comparator(Constant* a, Constant* b);
97 
98   // We use negative frequencies to keep the order of the
99   // jump-tables in which they were added.  Otherwise we get into
100   // trouble with relocation.
next_jump_table_freq()101   float next_jump_table_freq() { return -1.0f * (++_nof_jump_tables); }
102 
103 public:
ConstantTable()104   ConstantTable() :
105     _size(-1),
106     _table_base_offset(-1),  // We can use -1 here since the constant table is always bigger than 2 bytes (-(size / 2), see MachConstantBaseNode::emit).
107     _nof_jump_tables(0)
108   {}
109 
size() const110   int size() const { assert(_size != -1, "not calculated yet"); return _size; }
111 
112   int calculate_table_base_offset() const;  // AD specific
set_table_base_offset(int x)113   void set_table_base_offset(int x)  { assert(_table_base_offset == -1 || x == _table_base_offset, "can't change"); _table_base_offset = x; }
table_base_offset() const114   int      table_base_offset() const { assert(_table_base_offset != -1, "not set yet");                      return _table_base_offset; }
115 
116   bool emit(CodeBuffer& cb) const;
117 
118   // Returns the offset of the last entry (the top) of the constant table.
top_offset() const119   int  top_offset() const { assert(_constants.top().offset() != -1, "not bound yet"); return _constants.top().offset(); }
120 
121   void calculate_offsets_and_size();
122   int  find_offset(Constant& con) const;
123 
124   void     add(Constant& con);
125   Constant add(MachConstantNode* n, BasicType type, jvalue value);
126   Constant add(Metadata* metadata);
127   Constant add(MachConstantNode* n, MachOper* oper);
add(MachConstantNode * n,jint i)128   Constant add(MachConstantNode* n, jint i) {
129     jvalue value; value.i = i;
130     return add(n, T_INT, value);
131   }
add(MachConstantNode * n,jlong j)132   Constant add(MachConstantNode* n, jlong j) {
133     jvalue value; value.j = j;
134     return add(n, T_LONG, value);
135   }
add(MachConstantNode * n,jfloat f)136   Constant add(MachConstantNode* n, jfloat f) {
137     jvalue value; value.f = f;
138     return add(n, T_FLOAT, value);
139   }
add(MachConstantNode * n,jdouble d)140   Constant add(MachConstantNode* n, jdouble d) {
141     jvalue value; value.d = d;
142     return add(n, T_DOUBLE, value);
143   }
144 
145   // Jump-table
146   Constant  add_jump_table(MachConstantNode* n);
147   void     fill_jump_table(CodeBuffer& cb, MachConstantNode* n, GrowableArray<Label*> labels) const;
148 };
149 
150 
151 #endif // SHARE_OPTO_CONSTANTTABLE_HPP
152