@@ -49,23 +49,30 @@ class ValueRepReductionPhase : public Phase {
4949 bool run ()
5050 {
5151 ASSERT (m_graph.m_form == SSA);
52- return convertValueRepsToDouble ();
52+ bool changed = false ;
53+ changed |= convertValueRepsToUnboxed<DoubleRepUse>();
54+ changed |= convertValueRepsToUnboxed<Int52RepUse>();
55+ return changed;
5356 }
5457
5558private:
56- bool convertValueRepsToDouble ()
59+ template <UseKind useKind>
60+ bool convertValueRepsToUnboxed ()
5761 {
5862 UncheckedKeyHashSet<Node*> candidates;
5963 for (BasicBlock* block : m_graph.blocksInNaturalOrder ()) {
6064 for (Node* node : *block) {
6165 switch (node->op ()) {
6266 case ValueRep: {
63- if (node->child1 ().useKind () == DoubleRepUse )
67+ if (node->child1 ().useKind () == useKind )
6468 candidates.add (node);
6569 break ;
6670 }
6771
6872 case DoubleRep: {
73+ if constexpr (useKind != DoubleRepUse)
74+ break ;
75+
6976 if (!isARM64 () && !isX86_64_AVX ())
7077 break ;
7178
@@ -88,6 +95,50 @@ class ValueRepReductionPhase : public Phase {
8895 break ;
8996 }
9097
98+ case Int52Rep: {
99+ if constexpr (useKind != Int52RepUse)
100+ break ;
101+
102+ Edge& child1 = node->child1 ();
103+ switch (child1->op ()) {
104+ case MultiGetByVal: {
105+ if (child1->arrayMode ().isOutOfBounds ())
106+ break ;
107+
108+ if (child1->arrayMode ().isInBoundsSaneChain ())
109+ break ;
110+
111+ if (m_graph.hasExitSite (child1->origin .semantic , Int52Overflow))
112+ break ;
113+
114+ constexpr ArrayModes supportedArrays = 0
115+ | asArrayModesIgnoringTypedArrays (ArrayWithInt32)
116+ | asArrayModesIgnoringTypedArrays (ArrayWithDouble)
117+ | Int8ArrayMode
118+ | Int16ArrayMode
119+ | Int32ArrayMode
120+ | Uint8ArrayMode
121+ | Uint8ClampedArrayMode
122+ | Uint16ArrayMode
123+ | Uint32ArrayMode
124+ | 0 ;
125+
126+ if (!(child1->arrayModes () & supportedArrays))
127+ break ;
128+
129+ if (child1.useKind () == AnyIntUse) {
130+ if (child1->origin .exitOK )
131+ candidates.add (child1.node ());
132+ break ;
133+ }
134+ break ;
135+ }
136+ default :
137+ break ;
138+ }
139+ break ;
140+ }
141+
91142 default :
92143 break ;
93144 }
@@ -117,8 +168,21 @@ class ValueRepReductionPhase : public Phase {
117168 case GetGlobalLexicalVariable:
118169 case MultiGetByOffset:
119170 case GetByOffset: {
171+ if constexpr (useKind != DoubleRepUse)
172+ break ;
173+
120174 if (!isARM64 () && !isX86_64_AVX ())
121175 break ;
176+
177+ if (candidates.contains (node))
178+ usersOf.add (node, Vector<Node*>());
179+ break ;
180+ }
181+
182+ case MultiGetByVal: {
183+ if constexpr (useKind != Int52RepUse)
184+ break ;
185+
122186 if (candidates.contains (node))
123187 usersOf.add (node, Vector<Node*>());
124188 break ;
@@ -155,7 +219,7 @@ class ValueRepReductionPhase : public Phase {
155219 // makes Phi-1 a candidate too.
156220 do {
157221 UncheckedKeyHashSet<Node*> eligiblePhis;
158- for (Node * candidate : candidates) {
222+ for (auto * candidate : candidates) {
159223 if (candidate->op () == Phi) {
160224 phiChildren.forAllIncomingValues (candidate, [&] (Node* incoming) {
161225 if (incoming->op () == Phi)
@@ -193,7 +257,7 @@ class ValueRepReductionPhase : public Phase {
193257 // - A JSConstant(some number "x") => DoubleConstant("x")
194258 // - ValueRep(DoubleRepUse:@x) => @x
195259 // - A Phi so long as that Phi is not escaped.
196- for (Node * candidate : candidates) {
260+ for (auto * candidate : candidates) {
197261 bool ok = true ;
198262
199263 auto dumpEscape = [&](const char * description, Node* node) {
@@ -213,9 +277,17 @@ class ValueRepReductionPhase : public Phase {
213277 phiChildren.forAllIncomingValues (candidate, [&] (Node* node) {
214278 switch (node->op ()) {
215279 case JSConstant: {
216- if (!node->asJSValue ().isNumber ()) {
217- ok = false ;
218- dumpEscape (" Phi Incoming JSConstant not a number: " , node);
280+ if constexpr (useKind == DoubleRepUse) {
281+ if (!node->asJSValue ().isNumber ()) {
282+ ok = false ;
283+ dumpEscape (" Phi Incoming JSConstant not a number: " , node);
284+ }
285+ }
286+ if constexpr (useKind == Int52RepUse) {
287+ if (!node->asJSValue ().isAnyInt ()) {
288+ ok = false ;
289+ dumpEscape (" Phi Incoming JSConstant not a anyint: " , node);
290+ }
219291 }
220292 break ;
221293 }
@@ -231,17 +303,39 @@ class ValueRepReductionPhase : public Phase {
231303 break ;
232304 }
233305
306+ if constexpr (useKind != DoubleRepUse) {
307+ ok = false ;
308+ dumpEscape (" Phi Incoming Get is escaped: " , node);
309+ break ;
310+ }
311+
312+ if (isEscaped (node)) {
313+ ok = false ;
314+ dumpEscape (" Phi Incoming Get is escaped: " , node);
315+ break ;
316+ }
317+ break ;
318+ }
319+
320+ case MultiGetByVal: {
321+ if constexpr (useKind != Int52RepUse) {
322+ ok = false ;
323+ dumpEscape (" Phi Incoming Get is escaped: " , node);
324+ break ;
325+ }
326+
234327 if (isEscaped (node)) {
235328 ok = false ;
236329 dumpEscape (" Phi Incoming Get is escaped: " , node);
330+ break ;
237331 }
238332 break ;
239333 }
240334
241335 case ValueRep: {
242- if (node->child1 ().useKind () != DoubleRepUse ) {
336+ if (node->child1 ().useKind () != useKind ) {
243337 ok = false ;
244- dumpEscape (" Phi Incoming ValueRep not DoubleRepUse: " , node);
338+ dumpEscape (" Phi Incoming ValueRep not DoubleRepUse / Int52RepUse : " , node);
245339 }
246340 break ;
247341 }
@@ -271,6 +365,11 @@ class ValueRepReductionPhase : public Phase {
271365 for (Node* user : getUsersOf (candidate)) {
272366 switch (user->op ()) {
273367 case DoubleRep: {
368+ if constexpr (useKind != DoubleRepUse) {
369+ ok = false ;
370+ dumpEscape (" DoubleRep escape: " , user);
371+ break ;
372+ }
274373 switch (user->child1 ().useKind ()) {
275374 case RealNumberUse:
276375 case NumberUse:
@@ -284,6 +383,24 @@ class ValueRepReductionPhase : public Phase {
284383 break ;
285384 }
286385
386+ case Int52Rep: {
387+ if constexpr (useKind != Int52RepUse) {
388+ ok = false ;
389+ dumpEscape (" Int52RepUse escape: " , user);
390+ break ;
391+ }
392+ switch (user->child1 ().useKind ()) {
393+ case AnyIntUse:
394+ break ;
395+ default : {
396+ ok = false ;
397+ dumpEscape (" Int52Rep escape: " , user);
398+ break ;
399+ }
400+ }
401+ break ;
402+ }
403+
287404 case PutHint:
288405 case MovHint:
289406 break ;
@@ -293,6 +410,12 @@ class ValueRepReductionPhase : public Phase {
293410 case MultiPutByOffset:
294411 case PutClosureVar:
295412 case PutGlobalVariable:
413+ if constexpr (useKind != DoubleRepUse) {
414+ ok = false ;
415+ dumpEscape (" Normal escape: " , user);
416+ break ;
417+ }
418+
296419 if (!isARM64 () && !isX86_64_AVX ()) {
297420 dumpEscape (" Normal escape: " , user);
298421 ok = false ;
@@ -336,8 +459,8 @@ class ValueRepReductionPhase : public Phase {
336459 NodeOrigin originForConstant = m_graph.block (0 )->at (0 )->origin ;
337460 UncheckedKeyHashSet<Node*> doubleRepRealCheckLocations;
338461
339- for (Node * candidate : candidates) {
340- dataLogLnIf (verbose, " Optimized: " , candidate);
462+ for (auto * candidate : candidates) {
463+ dataLogLnIf (verbose, " Optimized: " , candidate, " with " , useKind );
341464
342465 Node* resultNode = nullptr ;
343466 switch (candidate->op ()) {
@@ -349,14 +472,22 @@ class ValueRepReductionPhase : public Phase {
349472 Node* newChild = nullptr ;
350473 switch (incomingValue->op ()) {
351474 case JSConstant: {
352- double number = incomingValue->asJSValue ().asNumber ();
353- newChild = m_insertionSet.insertConstant (0 , originForConstant, jsDoubleNumber (number), DoubleConstant);
475+ if constexpr (useKind == DoubleRepUse) {
476+ double number = incomingValue->asJSValue ().asNumber ();
477+ newChild = m_insertionSet.insertConstant (0 , originForConstant, jsDoubleNumber (number), DoubleConstant);
478+ break ;
479+ }
480+ if constexpr (useKind == Int52RepUse) {
481+ int64_t number = incomingValue->asJSValue ().asAnyInt ();
482+ newChild = m_insertionSet.insertConstant (0 , originForConstant, jsNumber (number), Int52Constant);
483+ break ;
484+ }
354485 break ;
355486 }
356487 case ValueRep: {
357488 // We don't care about the incoming value being an impure NaN because users of
358489 // this Phi are either OSR exit, DoubleRep(RealNumberUse:@phi), or PurifyNaN(@phi).
359- ASSERT (incomingValue->child1 ().useKind () == DoubleRepUse );
490+ ASSERT (incomingValue->child1 ().useKind () == useKind );
360491 newChild = incomingValue->child1 ().node ();
361492 break ;
362493 }
@@ -376,15 +507,23 @@ class ValueRepReductionPhase : public Phase {
376507 break ;
377508 }
378509
510+ case MultiGetByVal: {
511+ newChild = incomingValue;
512+ break ;
513+ }
514+
379515 default :
380516 RELEASE_ASSERT_NOT_REACHED ();
381517 break ;
382518 }
383519
384- upsilon->child1 () = Edge (newChild, DoubleRepUse );
520+ upsilon->child1 () = Edge (newChild, useKind );
385521 }
386522
387- candidate->setResult (NodeResultDouble);
523+ if constexpr (useKind == DoubleRepUse)
524+ candidate->setResult (NodeResultDouble);
525+ if constexpr (useKind == Int52RepUse)
526+ candidate->setResult (NodeResultInt52);
388527 break ;
389528 }
390529
@@ -405,6 +544,12 @@ class ValueRepReductionPhase : public Phase {
405544 break ;
406545 }
407546
547+ case MultiGetByVal: {
548+ candidate->setResult (NodeResultInt52);
549+ resultNode = candidate;
550+ break ;
551+ }
552+
408553 default :
409554 RELEASE_ASSERT_NOT_REACHED ();
410555 break ;
@@ -420,37 +565,42 @@ class ValueRepReductionPhase : public Phase {
420565 user->convertToPurifyNaN (resultNode);
421566 break ;
422567 }
423-
568+
569+ case Int52Rep: {
570+ user->convertToIdentityOn (resultNode);
571+ break ;
572+ }
573+
424574 case PutHint:
425- user->child2 () = Edge (resultNode, DoubleRepUse );
575+ user->child2 () = Edge (resultNode, useKind );
426576 break ;
427577
428578 case MovHint:
429- user->child1 () = Edge (resultNode, DoubleRepUse );
579+ user->child1 () = Edge (resultNode, useKind );
430580 break ;
431581
432582 case PutByOffset:
433583 if (!isARM64 () && !isX86_64_AVX ())
434584 RELEASE_ASSERT_NOT_REACHED ();
435- user->child3 () = Edge (resultNode, DoubleRepUse );
585+ user->child3 () = Edge (resultNode, useKind );
436586 break ;
437587
438588 case MultiPutByOffset:
439589 if (!isARM64 () && !isX86_64_AVX ())
440590 RELEASE_ASSERT_NOT_REACHED ();
441- user->child2 () = Edge (resultNode, DoubleRepUse );
591+ user->child2 () = Edge (resultNode, useKind );
442592 break ;
443593
444594 case PutClosureVar:
445595 if (!isARM64 () && !isX86_64_AVX ())
446596 RELEASE_ASSERT_NOT_REACHED ();
447- user->child2 () = Edge (resultNode, DoubleRepUse );
597+ user->child2 () = Edge (resultNode, useKind );
448598 break ;
449599
450600 case PutGlobalVariable:
451601 if (!isARM64 () && !isX86_64_AVX ())
452602 RELEASE_ASSERT_NOT_REACHED ();
453- user->child2 () = Edge (resultNode, DoubleRepUse );
603+ user->child2 () = Edge (resultNode, useKind );
454604 break ;
455605
456606 case Upsilon: {
0 commit comments