aboutsummaryrefslogtreecommitdiff
path: root/src/experimental/stringCache.diff
blob: 26cbc68cddf6cdad8ef57988fe4fe20f55b3515d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
diff --git a/src/library_gl.js b/src/library_gl.js
index 7471578..9228964 100644
--- a/src/library_gl.js
+++ b/src/library_gl.js
@@ -1256,28 +1256,28 @@ var LibraryGL = {
 
     setClientAttribute: function(name, size, type, stride, pointer) {
       var attrib = this.clientAttributes[GL.immediate.ATTRIBUTE_BY_NAME[name]];
       attrib.size = size;
       attrib.type = type;
       attrib.stride = stride;
       attrib.pointer = pointer;
-      attrib.name = name + size;
+      attrib.name = Runtime.getStringConcat(name, size);
     },
 
     // Renderers
     addRendererComponent: function(component) {
       if (this.rendererComponents[component]) return;
       this.rendererComponents[component] = 1;
-      this.renderer += component;
+      this.renderer = Runtime.getStringConcat(this.renderer, component);
     },
 
     setRenderer: function(renderer) {
       var name = renderer;
       if (GL.currProgram && renderer[0] != 'U') {
-        name = 'UD' + GL.currProgram + '|' + renderer; // user-defined program renderer
+        name = Runtime.getStringConcat(Runtime.getStringConcat('UD', GL.currProgram), Runtime.getStringConcat('|', renderer)); // user-defined program renderer
       }
       this.renderer = name;
       if (this.renderers[name]) return this.renderers[name];
       this.renderers[name] = this.createRenderer(renderer);
       return this.renderers[name];
     },
 
@@ -1300,15 +1300,18 @@ var LibraryGL = {
           }
           vertexSize += size * 4; // XXX assuming float
         } else if (which == 'N') {
           vertexSize += 4; // 1 char, + alignment
         } else if (which == 'C') {
           vertexSize += 4; // Up to 4 chars, + alignment
         } else {
-          console.log('Warning: Ignoring renderer attribute ' + which);
+#if ASSERTIONS
+          console.log('Warning: Ignoring renderer attribute');
+          console.log(which);
+#endif
           size = parseInt(renderer[i+1]);
           vertexSize += size * 4; // XXX assuming float
         }
       }
       assert(positionSize > 0);
       // TODO: verify vertexSize is equal to the stride in enabled client arrays
       var useCurrProgram = !!GL.currProgram;
@@ -1465,30 +1468,30 @@ var LibraryGL = {
       var renderer = '', bytes = 0;
       for (var i = 0; i < attributes.length; i++) {
         var attribute = attributes[i];
         if (!attribute) break;
         attribute.offset = attribute.pointer - start;
         if (attribute.offset > bytes) { // ensure we start where we should
           assert((attribute.offset - bytes)%4 == 0); // XXX assuming 4-alignment
-          renderer += '?' + ((attribute.offset - bytes)/4);
+          renderer = Runtime.getStringConcat(renderer, Runtime.getStringConcat('?', ((attribute.offset - bytes)/4)));
           bytes += attribute.offset - bytes;
         }
-        renderer += attribute.name;
+        renderer = Runtime.getStringConcat(renderer, attribute.name);
         bytes += attribute.size * GL.immediate.byteSizeByType[attribute.type];
         if (bytes % 4 != 0) bytes += 4 - (bytes % 4); // XXX assuming 4-alignment
 #if ASSERTIONS
         assert(0 <= attribute.offset && attribute.offset < stride); // must all be in the same buffer
 #endif
       }
 
       assert(stride == 0 || bytes <= stride);
 
       if (bytes < stride) { // ensure the size is that of the stride
         assert((stride - bytes)%4 == 0); // assuming float
-        renderer += '?' + ((stride-bytes)/4);
+        renderer = Runtime.getStringConcat(renderer, Runtime.getStringConcat('?', ((stride-bytes)/4)));
         bytes = stride;
       }
 
       bytes *= count;
       if (!GL.currArrayBuffer) {
         GL.immediate.vertexData = {{{ makeHEAPView('F32', 'start', 'start + bytes') }}}; // XXX assuming float
       }
@@ -1671,15 +1674,15 @@ var LibraryGL = {
   },
 
   glVertexPointer__deps: ['$GLEmulation'], // if any pointers are used, glVertexPointer must be, and if it is, then we need emulation
   glVertexPointer: function(size, type, stride, pointer) {
     GL.immediate.setClientAttribute('V', size, type, stride, pointer);
   },
   glTexCoordPointer: function(size, type, stride, pointer) {
-    GL.immediate.setClientAttribute('T' + GL.immediate.clientActiveTexture, size, type, stride, pointer);
+    GL.immediate.setClientAttribute(Runtime.getStringConcat('T', GL.immediate.clientActiveTexture), size, type, stride, pointer);
   },
   glNormalPointer: function(type, stride, pointer) {
     GL.immediate.setClientAttribute('N', 1, type, stride, pointer);
   },
   glColorPointer: function(size, type, stride, pointer) {
     GL.immediate.setClientAttribute('C', size, type, stride, pointer);
   },
diff --git a/src/runtime.js b/src/runtime.js
index 6a251c4..012a66d 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -319,25 +319,34 @@ var Runtime = {
     if (!Runtime.warnOnce.shown) Runtime.warnOnce.shown = {};
     if (!Runtime.warnOnce.shown[text]) {
       Runtime.warnOnce.shown[text] = 1;
       Module.printErr(text);
     }
   },
 
+  // Cache for JS function wrappers for C functions in FUNCTION_TABLE
   funcWrappers: {},
-
   getFuncWrapper: function(func) {
     if (!Runtime.funcWrappers[func]) {
       Runtime.funcWrappers[func] = function() {
         FUNCTION_TABLE[func].apply(null, arguments);
       };
     }
     return Runtime.funcWrappers[func];
   },
 
+  // Cache for small recurring strings generated by concatenating other
+  // strings, use this to avoid needless allocation and collection
+  stringCache: {},
+  getStringConcat: function(a, b) {
+    var cacheItem = Runtime.stringCache[a];
+    if (!cacheItem) cacheItem = Runtime.stringCache[a] = {};
+    return cacheItem[b] || (cacheItem[b] = a + b);
+  },
+
 #if RUNTIME_DEBUG
   debug: true, // Switch to false at runtime to disable logging at the right times
 
   printObjectList: [],
 
   prettyPrint: function(arg) {
     if (typeof arg == 'undefined') return '!UNDEFINED!';