@@ -129,7 +129,7 @@ static void traversePost(Ref node, std::function<void(Ref)> visit) {
129129}
130130
131131static void optimizeJS (Ref ast) {
132- // helpers
132+ // Helpers
133133
134134 auto isOrZero = [](Ref node) {
135135 return node->isArray () && !node->empty () && node[0 ] == BINARY &&
@@ -141,6 +141,11 @@ static void optimizeJS(Ref ast) {
141141 node[1 ] == PLUS;
142142 };
143143
144+ auto isFround = [](Ref node) {
145+ return node->isArray () && !node->empty () && node[0 ] == cashew::CALL &&
146+ node[1 ] == MATH_FROUND;
147+ };
148+
144149 auto isBitwise = [](Ref node) {
145150 if (node->isArray () && !node->empty () && node[0 ] == BINARY) {
146151 auto op = node[1 ];
@@ -150,6 +155,60 @@ static void optimizeJS(Ref ast) {
150155 return false ;
151156 };
152157
158+ auto isConstantAnd = [](Ref node, int num) {
159+ return node->isArray () && !node->empty () && node[0 ] == BINARY &&
160+ node[1 ] == AND && node[3 ]->isNumber () && node[3 ]->getNumber () == num;
161+ };
162+
163+ auto removeOrZero = [&](Ref node) {
164+ while (isOrZero (node)) {
165+ node = node[2 ];
166+ }
167+ return node;
168+ };
169+
170+ auto removePlus = [&](Ref node) {
171+ while (isPlus (node)) {
172+ node = node[2 ];
173+ }
174+ return node;
175+ };
176+
177+ auto removePlusAndFround = [&](Ref node) {
178+ while (1 ) {
179+ if (isFround (node)) {
180+ node = node[2 ][0 ];
181+ } else if (isPlus (node)) {
182+ node = node[2 ];
183+ } else {
184+ break ;
185+ }
186+ }
187+ return node;
188+ };
189+
190+ auto getHeapFromAccess = [](Ref node) { return node[1 ]->getIString (); };
191+
192+ auto isIntegerHeap = [](IString heap) {
193+ return heap == HEAP8 || heap == HEAPU8 || heap == HEAP16 ||
194+ heap == HEAPU16 || heap == HEAP32 || heap == HEAPU32;
195+ };
196+
197+ auto isFloatHeap = [](IString heap) {
198+ return heap == HEAPF32 || heap == HEAPF64;
199+ };
200+
201+ auto isHeapAccess = [&](Ref node) {
202+ if (node->isArray () && !node->empty () && node[0 ] == SUB &&
203+ node[1 ]->isString ()) {
204+ auto heap = getHeapFromAccess (node);
205+ return isIntegerHeap (heap) || isFloatHeap (heap);
206+ }
207+ return false ;
208+ };
209+
210+ // Optimizations
211+
153212 // x >> 0 => x | 0
154213 traversePost (ast, [](Ref node) {
155214 if (node->isArray () && !node->empty () && node[0 ] == BINARY &&
@@ -175,17 +234,46 @@ static void optimizeJS(Ref ast) {
175234 }
176235 // x | 0 going into a bitwise op => skip the | 0
177236 else if (isBitwise (node)) {
178- while (isOrZero (node[2 ])) {
179- node[2 ] = node[2 ][2 ];
180- }
181- while (isOrZero (node[3 ])) {
182- node[3 ] = node[3 ][2 ];
183- }
237+ node[2 ] = removeOrZero (node[2 ]);
238+ node[3 ] = removeOrZero (node[3 ]);
184239 }
185240 // +(+x) => +x
186241 else if (isPlus (node)) {
187- while (isPlus (node[2 ])) {
188- node[2 ] = node[2 ][2 ];
242+ node[2 ] = removePlus (node[2 ]);
243+ }
244+ // +(+x) => +x
245+ else if (isFround (node)) {
246+ node[2 ] = removePlusAndFround (node[2 ]);
247+ }
248+ // Assignment into a heap coerces.
249+ else if (node->isAssign ()) {
250+ auto assign = node->asAssign ();
251+ auto target = assign->target ();
252+ if (isHeapAccess (target)) {
253+ auto heap = getHeapFromAccess (target);
254+ if (isIntegerHeap (heap)) {
255+ if (heap == HEAP8 || heap == HEAPU8) {
256+ while (isOrZero (assign->value ()) ||
257+ isConstantAnd (assign->value (), 255 )) {
258+ assign->value () = assign->value ()[2 ];
259+ }
260+ } else if (heap == HEAP16 || heap == HEAPU16) {
261+ while (isOrZero (assign->value ()) ||
262+ isConstantAnd (assign->value (), 65535 )) {
263+ assign->value () = assign->value ()[2 ];
264+ }
265+ } else {
266+ assert (heap == HEAP32 || heap == HEAPU32);
267+ assign->value () = removeOrZero (assign->value ());
268+ }
269+ } else {
270+ assert (isFloatHeap (heap));
271+ if (heap == HEAPF32) {
272+ assign->value () = removePlusAndFround (assign->value ());
273+ } else {
274+ assign->value () = removePlus (assign->value ());
275+ }
276+ }
189277 }
190278 }
191279 });
0 commit comments