Make JetStream 2
[WebKit-https.git] / PerformanceTests / JetStream2 / WSL / Intrinsics.js
1 /*
2  * Copyright (C) 2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25 "use strict";
26
27 class Intrinsics {
28     constructor(nameContext)
29     {
30         this._map = new Map();
31
32         // NOTE: Intrinsic resolution happens before type name resolution, so the strings we use here
33         // to catch the intrinsics must be based on the type names that StandardLibraryPrologue.js uses.
34         // For example, if a native function is declared using "int" rather than "int32", then we must
35         // use "int" here, since we don't yet know that they are the same type.
36         
37         this._map.set(
38             "native typedef void<>",
39             type => {
40                 this.void = type;
41                 type.size = 0;
42                 type.populateDefaultValue = () => { };
43             });
44         
45         function isBitwiseEquivalent(left, right)
46         {
47             let doubleArray = new Float64Array(1);
48             let intArray = new Int32Array(doubleArray.buffer);
49             doubleArray[0] = left;
50             let leftInts = Int32Array.from(intArray);
51             doubleArray[0] = right;
52             for (let i = 0; i < 2; ++i) {
53                 if (leftInts[i] != intArray[i])
54                     return false;
55             }
56             return true;
57         }
58
59         this._map.set(
60             "native typedef int32<>",
61             type => {
62                 this.int32 = type;
63                 type.isPrimitive = true;
64                 type.isInt = true;
65                 type.isNumber = true;
66                 type.isSigned = true;
67                 type.canRepresent = value => isBitwiseEquivalent(value | 0, value);
68                 type.size = 1;
69                 type.defaultValue = 0;
70                 type.createLiteral = (origin, value) => IntLiteral.withType(origin, value | 0, type);
71                 type.successorValue = value => (value + 1) | 0;
72                 type.valuesEqual = (a, b) => a === b;
73                 type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
74                 type.formatValueFromIntLiteral = value => value | 0;
75                 type.formatValueFromUintLiteral = value => value | 0;
76                 type.allValues = function*() { 
77                     for (let i = 0; i <= 0xffffffff; ++i) {
78                         let value = i | 0;
79                         yield {value: value, name: value};
80                     }
81                 };
82             });
83
84         this._map.set(
85             "native typedef uint32<>",
86             type => {
87                 this.uint32 = type;
88                 type.isPrimitive = true;
89                 type.isInt = true;
90                 type.isNumber = true;
91                 type.isSigned = false;
92                 type.canRepresent = value => isBitwiseEquivalent(value >>> 0, value);
93                 type.size = 1;
94                 type.defaultValue = 0;
95                 type.createLiteral = (origin, value) => IntLiteral.withType(origin, value >>> 0, type);
96                 type.successorValue = value => (value + 1) >>> 0;
97                 type.valuesEqual = (a, b) => a === b;
98                 type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
99                 type.formatValueFromIntLiteral = value => value >>> 0;
100                 type.formatValueFromUintLiteral = value => value >>> 0;
101                 type.allValues = function*() { 
102                     for (let i = 0; i <= 0xffffffff; ++i)
103                         yield {value: i, name: i};
104                 };
105             });
106
107         this._map.set(
108             "native typedef uint8<>",
109             type => {
110                 this.uint8 = type;
111                 type.isInt = true;
112                 type.isNumber = true;
113                 type.isSigned = false;
114                 type.canRepresent = value => isBitwiseEquivalent(value & 0xff, value);
115                 type.size = 1;
116                 type.defaultValue = 0;
117                 type.createLiteral = (origin, value) => IntLiteral.withType(origin, value & 0xff, type);
118                 type.successorValue = value => (value + 1) & 0xff;
119                 type.valuesEqual = (a, b) => a === b;
120                 type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
121                 type.formatValueFromIntLiteral = value => value & 0xff;
122                 type.formatValueFromUintLiteral = value => value & 0xff;
123                 type.allValues = function*() {
124                     for (let i = 0; i <= 0xff; ++i)
125                         yield {value: i, name: i};
126                 };
127             });
128
129         this._map.set(
130             "native typedef float32<>",
131             type => {
132                 this.float = type;
133                 type.isPrimitive = true;
134                 type.size = 1;
135                 type.isFloating = true;
136                 type.isNumber = true;
137                 type.canRepresent = value => isBitwiseEquivalent(Math.fround(value), value);
138                 type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
139                 type.formatValueFromIntLiteral = value => value;
140                 type.formatValueFromUintLiteral = value => value;
141                 type.formatValueFromFloatLiteral = value => Math.fround(value);
142                 type.formatValueFromDoubleLiteral = value => Math.fround(value);
143             });
144
145         this._map.set(
146             "native typedef float64<>",
147             type => {
148                 this.double = type;
149                 type.isPrimitive = true;
150                 type.size = 1;
151                 type.isFloating = true;
152                 type.isNumber = true;
153                 type.canRepresent = value => true;
154                 type.populateDefaultValue = (buffer, offset) => buffer.set(offset, 0);
155                 type.formatValueFromIntLiteral = value => value;
156                 type.formatValueFromUintLiteral = value => value;
157                 type.formatValueFromFloatLiteral = value => value;
158                 type.formatValueFromDoubleLiteral = value => value;
159             });
160
161         this._map.set(
162             "native typedef bool<>",
163             type => {
164                 this.bool = type;
165                 type.isPrimitive = true;
166                 type.size = 1;
167                 type.populateDefaultValue = (buffer, offset) => buffer.set(offset, false);
168             });
169         
170         this._map.set(
171             "native operator<> int32(uint32)",
172             func => {
173                 func.implementation = ([value]) => EPtr.box(value.loadValue() | 0);
174             });
175         
176         this._map.set(
177             "native operator<> int32(uint8)",
178             func => {
179                 func.implementation = ([value]) => EPtr.box(value.loadValue() | 0);
180             });
181         
182         this._map.set(
183             "native operator<> int32(float)",
184             func => {
185                 func.implementation = ([value]) => EPtr.box(value.loadValue() | 0);
186             });
187         
188         this._map.set(
189             "native operator<> int32(double)",
190             func => {
191                 func.implementation = ([value]) => EPtr.box(value.loadValue() | 0);
192             });
193         
194         this._map.set(
195             "native operator<> uint32(int32)",
196             func => {
197                 func.implementation = ([value]) => EPtr.box(value.loadValue() >>> 0);
198             });
199         
200         this._map.set(
201             "native operator<> uint32(uint8)",
202             func => {
203                 func.implementation = ([value]) => EPtr.box(value.loadValue() >>> 0);
204             });
205         
206         this._map.set(
207             "native operator<> uint32(float)",
208             func => {
209                 func.implementation = ([value]) => EPtr.box(value.loadValue() >>> 0);
210             });
211         
212         this._map.set(
213             "native operator<> uint32(double)",
214             func => {
215                 func.implementation = ([value]) => EPtr.box(value.loadValue() >>> 0);
216             });
217         
218         this._map.set(
219             "native operator<> uint8(int32)",
220             func => {
221                 func.implementation = ([value]) => EPtr.box(value.loadValue() & 0xff);
222             });
223         
224         this._map.set(
225             "native operator<> uint8(uint32)",
226             func => {
227                 func.implementation = ([value]) => EPtr.box(value.loadValue() & 0xff);
228             });
229         
230         this._map.set(
231             "native operator<> uint8(float)",
232             func => {
233                 func.implementation = ([value]) => EPtr.box(value.loadValue() & 0xff);
234             });
235         
236         this._map.set(
237             "native operator<> uint8(double)",
238             func => {
239                 func.implementation = ([value]) => EPtr.box(value.loadValue() & 0xff);
240             });
241         
242         this._map.set(
243             "native operator<> float(double)",
244             func => {
245                 func.implementation = ([value]) => EPtr.box(Math.fround(value.loadValue()));
246             });
247         
248         this._map.set(
249             "native operator<> float(int32)",
250             func => {
251                 func.implementation = ([value]) => EPtr.box(Math.fround(value.loadValue()));
252             });
253         
254         this._map.set(
255             "native operator<> float(uint32)",
256             func => {
257                 func.implementation = ([value]) => EPtr.box(Math.fround(value.loadValue()));
258             });
259         
260         this._map.set(
261             "native operator<> float(uint8)",
262             func => {
263                 func.implementation = ([value]) => EPtr.box(Math.fround(value.loadValue()));
264             });
265         
266         this._map.set(
267             "native operator<> double(float)",
268             func => {
269                 func.implementation = ([value]) => EPtr.box(value.loadValue());
270             });
271         
272         this._map.set(
273             "native operator<> double(int32)",
274             func => {
275                 func.implementation = ([value]) => EPtr.box(value.loadValue());
276             });
277         
278         this._map.set(
279             "native operator<> double(uint32)",
280             func => {
281                 func.implementation = ([value]) => EPtr.box(value.loadValue());
282             });
283         
284         this._map.set(
285             "native operator<> double(uint8)",
286             func => {
287                 func.implementation = ([value]) => EPtr.box(value.loadValue());
288             });
289         
290         this._map.set(
291             "native int operator+<>(int,int)",
292             func => {
293                 func.implementation = ([left, right]) =>
294                     EPtr.box((left.loadValue() + right.loadValue()) | 0);
295             });
296         
297         this._map.set(
298             "native uint operator+<>(uint,uint)",
299             func => {
300                 func.implementation = ([left, right]) =>
301                     EPtr.box((left.loadValue() + right.loadValue()) >>> 0);
302             });
303         
304         this._map.set(
305             "native float operator+<>(float,float)",
306             func => {
307                 func.implementation = ([left, right]) =>
308                     EPtr.box(Math.fround(left.loadValue() + right.loadValue()));
309             });
310         
311         this._map.set(
312             "native double operator+<>(double,double)",
313             func => {
314                 func.implementation = ([left, right]) =>
315                     EPtr.box(left.loadValue() + right.loadValue());
316             });
317         
318         this._map.set(
319             "native int operator-<>(int,int)",
320             func => {
321                 func.implementation = ([left, right]) =>
322                     EPtr.box((left.loadValue() - right.loadValue()) | 0);
323             });
324         
325         this._map.set(
326             "native uint operator-<>(uint,uint)",
327             func => {
328                 func.implementation = ([left, right]) =>
329                     EPtr.box((left.loadValue() - right.loadValue()) >>> 0);
330             });
331         
332         this._map.set(
333             "native float operator-<>(float,float)",
334             func => {
335                 func.implementation = ([left, right]) =>
336                     EPtr.box(Math.fround(left.loadValue() - right.loadValue()));
337             });
338         
339         this._map.set(
340             "native double operator-<>(double,double)",
341             func => {
342                 func.implementation = ([left, right]) =>
343                     EPtr.box(left.loadValue() - right.loadValue());
344             });
345         
346         this._map.set(
347             "native int operator*<>(int,int)",
348             func => {
349                 func.implementation = ([left, right]) =>
350                     EPtr.box((left.loadValue() * right.loadValue()) | 0);
351             });
352         
353         this._map.set(
354             "native uint operator*<>(uint,uint)",
355             func => {
356                 func.implementation = ([left, right]) =>
357                     EPtr.box((left.loadValue() * right.loadValue()) >>> 0);
358             });
359         
360         this._map.set(
361             "native float operator*<>(float,float)",
362             func => {
363                 func.implementation = ([left, right]) =>
364                     EPtr.box(Math.fround(left.loadValue() * right.loadValue()));
365             });
366         
367         this._map.set(
368             "native double operator*<>(double,double)",
369             func => {
370                 func.implementation = ([left, right]) =>
371                     EPtr.box(left.loadValue() * right.loadValue());
372             });
373         
374         this._map.set(
375             "native int operator/<>(int,int)",
376             func => {
377                 func.implementation = ([left, right]) =>
378                     EPtr.box((left.loadValue() / right.loadValue()) | 0);
379             });
380         
381         this._map.set(
382             "native uint operator/<>(uint,uint)",
383             func => {
384                 func.implementation = ([left, right]) =>
385                     EPtr.box((left.loadValue() / right.loadValue()) >>> 0);
386             });
387         
388         this._map.set(
389             "native int operator&<>(int,int)",
390             func => {
391                 func.implementation = ([left, right]) =>
392                     EPtr.box(left.loadValue() & right.loadValue());
393             });
394         
395         this._map.set(
396             "native uint operator&<>(uint,uint)",
397             func => {
398                 func.implementation = ([left, right]) =>
399                     EPtr.box((left.loadValue() & right.loadValue()) >>> 0);
400             });
401         
402         this._map.set(
403             "native int operator|<>(int,int)",
404             func => {
405                 func.implementation = ([left, right]) =>
406                     EPtr.box(left.loadValue() | right.loadValue());
407             });
408         
409         this._map.set(
410             "native uint operator|<>(uint,uint)",
411             func => {
412                 func.implementation = ([left, right]) =>
413                     EPtr.box((left.loadValue() | right.loadValue()) >>> 0);
414             });
415         
416         this._map.set(
417             "native int operator^<>(int,int)",
418             func => {
419                 func.implementation = ([left, right]) =>
420                     EPtr.box(left.loadValue() ^ right.loadValue());
421             });
422         
423         this._map.set(
424             "native uint operator^<>(uint,uint)",
425             func => {
426                 func.implementation = ([left, right]) =>
427                     EPtr.box((left.loadValue() ^ right.loadValue()) >>> 0);
428             });
429         
430         this._map.set(
431             "native int operator<<<>(int,uint)",
432             func => {
433                 func.implementation = ([left, right]) =>
434                     EPtr.box(left.loadValue() << right.loadValue());
435             });
436         
437         this._map.set(
438             "native uint operator<<<>(uint,uint)",
439             func => {
440                 func.implementation = ([left, right]) =>
441                     EPtr.box((left.loadValue() << right.loadValue()) >>> 0);
442             });
443         
444         this._map.set(
445             "native int operator>><>(int,uint)",
446             func => {
447                 func.implementation = ([left, right]) =>
448                     EPtr.box(left.loadValue() >> right.loadValue());
449             });
450         
451         this._map.set(
452             "native uint operator>><>(uint,uint)",
453             func => {
454                 func.implementation = ([left, right]) =>
455                     EPtr.box(left.loadValue() >>> right.loadValue());
456             });
457         
458         this._map.set(
459             "native int operator~<>(int)",
460             func => {
461                 func.implementation = ([value]) => EPtr.box(~value.loadValue());
462             });
463         
464         this._map.set(
465             "native uint operator~<>(uint)",
466             func => {
467                 func.implementation = ([value]) => EPtr.box((~value.loadValue()) >>> 0);
468             });
469         
470         this._map.set(
471             "native float operator/<>(float,float)",
472             func => {
473                 func.implementation = ([left, right]) =>
474                     EPtr.box(Math.fround(left.loadValue() / right.loadValue()));
475             });
476         
477         this._map.set(
478             "native double operator/<>(double,double)",
479             func => {
480                 func.implementation = ([left, right]) =>
481                     EPtr.box(left.loadValue() / right.loadValue());
482             });
483         
484         this._map.set(
485             "native bool operator==<>(int,int)",
486             func => {
487                 func.implementation = ([left, right]) =>
488                     EPtr.box(left.loadValue() == right.loadValue());
489             });
490         
491         this._map.set(
492             "native bool operator==<>(uint,uint)",
493             func => {
494                 func.implementation = ([left, right]) =>
495                     EPtr.box(left.loadValue() == right.loadValue());
496             });
497         
498         this._map.set(
499             "native bool operator==<>(bool,bool)",
500             func => {
501                 func.implementation = ([left, right]) =>
502                     EPtr.box(left.loadValue() == right.loadValue());
503             });
504         
505         this._map.set(
506             "native bool operator==<>(float,float)",
507             func => {
508                 func.implementation = ([left, right]) =>
509                     EPtr.box(left.loadValue() == right.loadValue());
510             });
511         
512         this._map.set(
513             "native bool operator==<>(double,double)",
514             func => {
515                 func.implementation = ([left, right]) =>
516                     EPtr.box(left.loadValue() == right.loadValue());
517             });
518         
519         this._map.set(
520             "native bool operator<<>(int,int)",
521             func => {
522                 func.implementation = ([left, right]) =>
523                     EPtr.box(left.loadValue() < right.loadValue());
524             });
525         
526         this._map.set(
527             "native bool operator<<>(uint,uint)",
528             func => {
529                 func.implementation = ([left, right]) =>
530                     EPtr.box(left.loadValue() < right.loadValue());
531             });
532         
533         this._map.set(
534             "native bool operator<<>(float,float)",
535             func => {
536                 func.implementation = ([left, right]) =>
537                     EPtr.box(left.loadValue() < right.loadValue());
538             });
539         
540         this._map.set(
541             "native bool operator<<>(double,double)",
542             func => {
543                 func.implementation = ([left, right]) =>
544                     EPtr.box(left.loadValue() < right.loadValue());
545             });
546         
547         this._map.set(
548             "native bool operator<=<>(int,int)",
549             func => {
550                 func.implementation = ([left, right]) =>
551                     EPtr.box(left.loadValue() <= right.loadValue());
552             });
553         
554         this._map.set(
555             "native bool operator<=<>(uint,uint)",
556             func => {
557                 func.implementation = ([left, right]) =>
558                     EPtr.box(left.loadValue() <= right.loadValue());
559             });
560         
561         this._map.set(
562             "native bool operator<=<>(float,float)",
563             func => {
564                 func.implementation = ([left, right]) =>
565                     EPtr.box(left.loadValue() <= right.loadValue());
566             });
567         
568         this._map.set(
569             "native bool operator<=<>(double,double)",
570             func => {
571                 func.implementation = ([left, right]) =>
572                     EPtr.box(left.loadValue() <= right.loadValue());
573             });
574         
575         this._map.set(
576             "native bool operator><>(int,int)",
577             func => {
578                 func.implementation = ([left, right]) =>
579                     EPtr.box(left.loadValue() > right.loadValue());
580             });
581         
582         this._map.set(
583             "native bool operator><>(uint,uint)",
584             func => {
585                 func.implementation = ([left, right]) =>
586                     EPtr.box(left.loadValue() > right.loadValue());
587             });
588         
589         this._map.set(
590             "native bool operator><>(float,float)",
591             func => {
592                 func.implementation = ([left, right]) =>
593                     EPtr.box(left.loadValue() > right.loadValue());
594             });
595         
596         this._map.set(
597             "native bool operator><>(double,double)",
598             func => {
599                 func.implementation = ([left, right]) =>
600                     EPtr.box(left.loadValue() > right.loadValue());
601             });
602         
603         this._map.set(
604             "native bool operator>=<>(int,int)",
605             func => {
606                 func.implementation = ([left, right]) =>
607                     EPtr.box(left.loadValue() >= right.loadValue());
608             });
609         
610         this._map.set(
611             "native bool operator>=<>(uint,uint)",
612             func => {
613                 func.implementation = ([left, right]) =>
614                     EPtr.box(left.loadValue() >= right.loadValue());
615             });
616         
617         this._map.set(
618             "native bool operator>=<>(float,float)",
619             func => {
620                 func.implementation = ([left, right]) =>
621                     EPtr.box(left.loadValue() >= right.loadValue());
622             });
623         
624         this._map.set(
625             "native bool operator>=<>(double,double)",
626             func => {
627                 func.implementation = ([left, right]) =>
628                     EPtr.box(left.loadValue() >= right.loadValue());
629             });
630         
631         for (let addressSpace of addressSpaces) {
632             this._map.set(
633                 `native T* ${addressSpace} operator&[]<T>(T[] ${addressSpace},uint)`,
634                 func => {
635                     func.implementation = ([ref, index], node) => {
636                         ref = ref.loadValue();
637                         if (!ref)
638                             throw new WTrapError(node.origin.originString, "Null dereference");
639                         index = index.loadValue();
640                         if (index > ref.length)
641                             throw new WTrapError(node.origin.originString, "Array index " + index + " is out of bounds of " + ref);
642                         return EPtr.box(ref.ptr.plus(index * node.instantiatedActualTypeArguments[0].size));
643                     };
644                 });
645
646             this._map.set(
647                 `native uint operator.length<T>(T[] ${addressSpace})`,
648                 func => {
649                     func.implementation = ([ref], node) => {
650                         ref = ref.loadValue();
651                         if (!ref)
652                             return EPtr.box(0);
653                         return EPtr.box(ref.length);
654                     };
655                 });
656         }
657     }
658     
659     add(thing)
660     {
661         let intrinsic = this._map.get(thing.toString());
662         if (!intrinsic)
663             throw new WTypeError(thing.origin.originString, "Unrecognized intrinsic: " + thing);
664         intrinsic(thing);
665     }
666 }
667