1 /*
2  * Copyright (c) 2016, 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 package org.graalvm.compiler.hotspot.replacements;
26 
27 import java.io.ByteArrayOutputStream;
28 import java.io.DataOutputStream;
29 import java.nio.ByteBuffer;
30 
31 import org.graalvm.compiler.core.common.PermanentBailoutException;
32 import org.graalvm.compiler.core.common.type.DataPointerConstant;
33 
34 import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
35 import jdk.vm.ci.hotspot.HotSpotObjectConstant;
36 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
37 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
38 import jdk.vm.ci.meta.Constant;
39 
40 /**
41  * Represents an encoded representation of a constant.
42  */
43 public final class EncodedSymbolConstant extends DataPointerConstant {
44     private final Constant constant;
45     private byte[] bytes;
46 
EncodedSymbolConstant(Constant constant)47     public EncodedSymbolConstant(Constant constant) {
48         super(1);
49         this.constant = constant;
50     }
51 
52     @Override
getSerializedSize()53     public int getSerializedSize() {
54         return getEncodedConstant().length;
55     }
56 
57     @Override
serialize(ByteBuffer buffer)58     public void serialize(ByteBuffer buffer) {
59         buffer.put(getEncodedConstant());
60     }
61 
62     /**
63      * Converts a string to a byte array with modified UTF-8 encoding. The first two bytes of the
64      * byte array store the length of the string in bytes.
65      *
66      * @param s a java.lang.String in UTF-16
67      */
toUTF8String(String s)68     private static byte[] toUTF8String(String s) {
69         try (ByteArrayOutputStream bytes = new ByteArrayOutputStream()) {
70             DataOutputStream stream = new DataOutputStream(bytes);
71             stream.writeUTF(s);
72             return bytes.toByteArray();
73         } catch (Exception e) {
74             throw new PermanentBailoutException(e, "String conversion failed: %s", s);
75         }
76     }
77 
encodeConstant(Constant constant)78     private static byte[] encodeConstant(Constant constant) {
79         assert constant != null;
80         if (constant instanceof HotSpotObjectConstant) {
81             return toUTF8String(((HotSpotObjectConstant) constant).asObject(String.class));
82         } else if (constant instanceof HotSpotMetaspaceConstant) {
83             HotSpotMetaspaceConstant metaspaceConstant = ((HotSpotMetaspaceConstant) constant);
84             HotSpotResolvedObjectType klass = metaspaceConstant.asResolvedJavaType();
85             if (klass != null) {
86                 return toUTF8String(klass.getName());
87             }
88             HotSpotResolvedJavaMethod method = metaspaceConstant.asResolvedJavaMethod();
89             if (method != null) {
90                 byte[] methodName = toUTF8String(method.getName());
91                 byte[] signature = toUTF8String(method.getSignature().toMethodDescriptor());
92                 byte[] result = new byte[methodName.length + signature.length];
93                 int resultPos = 0;
94                 System.arraycopy(methodName, 0, result, resultPos, methodName.length);
95                 resultPos += methodName.length;
96                 System.arraycopy(signature, 0, result, resultPos, signature.length);
97                 resultPos += signature.length;
98                 assert resultPos == result.length;
99                 return result;
100             }
101 
102         }
103         throw new PermanentBailoutException("Encoding of constant %s failed", constant);
104     }
105 
getEncodedConstant()106     public byte[] getEncodedConstant() {
107         if (bytes == null) {
108             bytes = encodeConstant(constant);
109         }
110         return bytes;
111     }
112 
113     @Override
toValueString()114     public String toValueString() {
115         return "encoded symbol\"" + constant.toValueString() + "\"";
116     }
117 
118 }
119