Reduce TLS accesses. (#11487)
[mono-project.git] / mono / metadata / dynamic-stream.c
blobe33bec79d3fa1121e61777a5e06e7baf5855c008
1 /**
2 * \file
3 * MonoDynamicStream
4 * Copyright 2016 Microsoft
6 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
7 */
9 #include <config.h>
10 #include <glib.h>
12 #include "mono/metadata/dynamic-stream-internals.h"
13 #include "mono/metadata/metadata-internals.h"
14 #include "mono/utils/checked-build.h"
15 #include "mono/utils/mono-error-internals.h"
16 #include "object-internals.h"
18 void
19 mono_dynstream_init (MonoDynamicStream *sh)
21 MONO_REQ_GC_NEUTRAL_MODE;
23 sh->index = 0;
24 sh->alloc_size = 4096;
25 sh->data = (char *)g_malloc (4096);
26 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
27 mono_dynstream_insert_string (sh, "");
30 static void
31 make_room_in_stream (MonoDynamicStream *stream, int size)
33 MONO_REQ_GC_NEUTRAL_MODE;
35 if (size <= stream->alloc_size)
36 return;
38 while (stream->alloc_size <= size) {
39 if (stream->alloc_size < 4096)
40 stream->alloc_size = 4096;
41 else
42 stream->alloc_size *= 2;
45 stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
48 guint32
49 mono_dynstream_insert_string (MonoDynamicStream *sh, const char *str)
51 MONO_REQ_GC_NEUTRAL_MODE;
53 guint32 idx;
54 guint32 len;
55 gpointer oldkey, oldval;
57 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
58 return GPOINTER_TO_UINT (oldval);
60 len = strlen (str) + 1;
61 idx = sh->index;
63 make_room_in_stream (sh, idx + len);
66 * We strdup the string even if we already copy them in sh->data
67 * so that the string pointers in the hash remain valid even if
68 * we need to realloc sh->data. We may want to avoid that later.
70 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
71 memcpy (sh->data + idx, str, len);
72 sh->index += len;
73 return idx;
76 guint32
77 mono_dynstream_insert_mstring (MonoDynamicStream *sh, MonoString *str, MonoError *error)
79 MONO_REQ_GC_UNSAFE_MODE;
81 error_init (error);
82 char *name = mono_string_to_utf8_checked_internal (str, error);
83 return_val_if_nok (error, -1);
84 guint32 idx;
85 idx = mono_dynstream_insert_string (sh, name);
86 g_free (name);
87 return idx;
90 guint32
91 mono_dynstream_add_data (MonoDynamicStream *stream, gconstpointer data, guint32 len)
93 MONO_REQ_GC_NEUTRAL_MODE;
95 guint32 idx;
97 make_room_in_stream (stream, stream->index + len);
98 memcpy (stream->data + stream->index, data, len);
99 idx = stream->index;
100 stream->index += len;
102 * align index? Not without adding an additional param that controls it since
103 * we may store a blob value in pieces.
105 return idx;
108 guint32
109 mono_dynstream_add_zero (MonoDynamicStream *stream, guint32 len)
111 MONO_REQ_GC_NEUTRAL_MODE;
113 guint32 idx;
115 make_room_in_stream (stream, stream->index + len);
116 memset (stream->data + stream->index, 0, len);
117 idx = stream->index;
118 stream->index += len;
119 return idx;
122 void
123 mono_dynstream_data_align (MonoDynamicStream *stream)
125 MONO_REQ_GC_NEUTRAL_MODE;
127 guint32 count = stream->index % 4;
129 /* we assume the stream data will be aligned */
130 if (count)
131 mono_dynstream_add_zero (stream, 4 - count);