1c6d9bcdf2d8a0c877ffaec87bfad67b147d3756
[WebKit-https.git] / Source / JavaScriptCore / b3 / B3Value.cpp
1 /*
2  * Copyright (C) 2015-2016 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
26 #include "config.h"
27 #include "B3Value.h"
28
29 #if ENABLE(B3_JIT)
30
31 #include "B3ArgumentRegValue.h"
32 #include "B3CCallValue.h"
33 #include "B3ControlValue.h"
34 #include "B3MemoryValue.h"
35 #include "B3OriginDump.h"
36 #include "B3ProcedureInlines.h"
37 #include "B3SlotBaseValue.h"
38 #include "B3StackSlot.h"
39 #include "B3UpsilonValue.h"
40 #include "B3ValueInlines.h"
41 #include "B3ValueKeyInlines.h"
42 #include "B3VariableValue.h"
43 #include <wtf/CommaPrinter.h>
44 #include <wtf/StringPrintStream.h>
45
46 namespace JSC { namespace B3 {
47
48 const char* const Value::dumpPrefix = "@";
49
50 Value::~Value()
51 {
52 }
53
54 void Value::replaceWithIdentity(Value* value)
55 {
56     // This is a bit crazy. It does an in-place replacement of whatever Value subclass this is with
57     // a plain Identity Value. We first collect all of the information we need, then we destruct the
58     // previous value in place, and then we construct the Identity Value in place.
59
60     ASSERT(m_type == value->m_type);
61
62     if (m_type == Void) {
63         replaceWithNop();
64         return;
65     }
66
67     unsigned index = m_index;
68     Type type = m_type;
69     Origin origin = m_origin;
70     BasicBlock* owner = this->owner;
71
72     RELEASE_ASSERT(type == value->type());
73
74     this->Value::~Value();
75
76     new (this) Value(Identity, type, origin, value);
77
78     this->owner = owner;
79     this->m_index = index;
80 }
81
82 void Value::replaceWithNop()
83 {
84     unsigned index = m_index;
85     Origin origin = m_origin;
86     BasicBlock* owner = this->owner;
87
88     this->Value::~Value();
89
90     new (this) Value(Nop, Void, origin);
91
92     this->owner = owner;
93     this->m_index = index;
94 }
95
96 void Value::replaceWithPhi()
97 {
98     if (m_type == Void) {
99         replaceWithNop();
100         return;
101     }
102     
103     unsigned index = m_index;
104     Origin origin = m_origin;
105     BasicBlock* owner = this->owner;
106     Type type = m_type;
107
108     this->Value::~Value();
109
110     new (this) Value(Phi, type, origin);
111
112     this->owner = owner;
113     this->m_index = index;
114 }
115
116 void Value::dump(PrintStream& out) const
117 {
118     bool isConstant = false;
119
120     switch (m_opcode) {
121     case Const32:
122         out.print("$", asInt32(), "(");
123         isConstant = true;
124         break;
125     case Const64:
126         out.print("$", asInt64(), "(");
127         isConstant = true;
128         break;
129     case ConstFloat:
130         out.print("$", asFloat(), "(");
131         isConstant = true;
132         break;
133     case ConstDouble:
134         out.print("$", asDouble(), "(");
135         isConstant = true;
136         break;
137     default:
138         break;
139     }
140     
141     out.print(dumpPrefix, m_index);
142
143     if (isConstant)
144         out.print(")");
145 }
146
147 Value* Value::cloneImpl() const
148 {
149     return new Value(*this);
150 }
151
152 void Value::dumpChildren(CommaPrinter& comma, PrintStream& out) const
153 {
154     for (Value* child : children())
155         out.print(comma, pointerDump(child));
156 }
157
158 void Value::deepDump(const Procedure* proc, PrintStream& out) const
159 {
160     out.print(m_type, " ", dumpPrefix, m_index, " = ", m_opcode);
161
162     out.print("(");
163     CommaPrinter comma;
164     dumpChildren(comma, out);
165
166     if (m_origin)
167         out.print(comma, OriginDump(proc, m_origin));
168
169     dumpMeta(comma, out);
170
171     {
172         CString string = toCString(effects());
173         if (string.length())
174             out.print(comma, string);
175     }
176
177     out.print(")");
178 }
179
180 Value* Value::negConstant(Procedure&) const
181 {
182     return nullptr;
183 }
184
185 Value* Value::addConstant(Procedure&, int32_t) const
186 {
187     return nullptr;
188 }
189
190 Value* Value::addConstant(Procedure&, const Value*) const
191 {
192     return nullptr;
193 }
194
195 Value* Value::subConstant(Procedure&, const Value*) const
196 {
197     return nullptr;
198 }
199
200 Value* Value::mulConstant(Procedure&, const Value*) const
201 {
202     return nullptr;
203 }
204
205 Value* Value::checkAddConstant(Procedure&, const Value*) const
206 {
207     return nullptr;
208 }
209
210 Value* Value::checkSubConstant(Procedure&, const Value*) const
211 {
212     return nullptr;
213 }
214
215 Value* Value::checkMulConstant(Procedure&, const Value*) const
216 {
217     return nullptr;
218 }
219
220 Value* Value::checkNegConstant(Procedure&) const
221 {
222     return nullptr;
223 }
224
225 Value* Value::divConstant(Procedure&, const Value*) const
226 {
227     return nullptr;
228 }
229
230 Value* Value::modConstant(Procedure&, const Value*) const
231 {
232     return nullptr;
233 }
234
235 Value* Value::bitAndConstant(Procedure&, const Value*) const
236 {
237     return nullptr;
238 }
239
240 Value* Value::bitOrConstant(Procedure&, const Value*) const
241 {
242     return nullptr;
243 }
244
245 Value* Value::bitXorConstant(Procedure&, const Value*) const
246 {
247     return nullptr;
248 }
249
250 Value* Value::shlConstant(Procedure&, const Value*) const
251 {
252     return nullptr;
253 }
254
255 Value* Value::sShrConstant(Procedure&, const Value*) const
256 {
257     return nullptr;
258 }
259
260 Value* Value::zShrConstant(Procedure&, const Value*) const
261 {
262     return nullptr;
263 }
264
265 Value* Value::bitwiseCastConstant(Procedure&) const
266 {
267     return nullptr;
268 }
269
270 Value* Value::doubleToFloatConstant(Procedure&) const
271 {
272     return nullptr;
273 }
274
275 Value* Value::floatToDoubleConstant(Procedure&) const
276 {
277     return nullptr;
278 }
279
280 Value* Value::absConstant(Procedure&) const
281 {
282     return nullptr;
283 }
284
285 Value* Value::ceilConstant(Procedure&) const
286 {
287     return nullptr;
288 }
289
290 Value* Value::sqrtConstant(Procedure&) const
291 {
292     return nullptr;
293 }
294
295 TriState Value::equalConstant(const Value*) const
296 {
297     return MixedTriState;
298 }
299
300 TriState Value::notEqualConstant(const Value*) const
301 {
302     return MixedTriState;
303 }
304
305 TriState Value::lessThanConstant(const Value*) const
306 {
307     return MixedTriState;
308 }
309
310 TriState Value::greaterThanConstant(const Value*) const
311 {
312     return MixedTriState;
313 }
314
315 TriState Value::lessEqualConstant(const Value*) const
316 {
317     return MixedTriState;
318 }
319
320 TriState Value::greaterEqualConstant(const Value*) const
321 {
322     return MixedTriState;
323 }
324
325 TriState Value::aboveConstant(const Value*) const
326 {
327     return MixedTriState;
328 }
329
330 TriState Value::belowConstant(const Value*) const
331 {
332     return MixedTriState;
333 }
334
335 TriState Value::aboveEqualConstant(const Value*) const
336 {
337     return MixedTriState;
338 }
339
340 TriState Value::belowEqualConstant(const Value*) const
341 {
342     return MixedTriState;
343 }
344
345 TriState Value::equalOrUnorderedConstant(const Value*) const
346 {
347     return MixedTriState;
348 }
349
350 Value* Value::invertedCompare(Procedure& proc) const
351 {
352     if (!numChildren())
353         return nullptr;
354     if (Optional<Opcode> invertedOpcode = B3::invertedCompare(opcode(), child(0)->type()))
355         return proc.add<Value>(*invertedOpcode, type(), origin(), children());
356     return nullptr;
357 }
358
359 bool Value::returnsBool() const
360 {
361     if (type() != Int32)
362         return false;
363     switch (opcode()) {
364     case Const32:
365         return asInt32() == 0 || asInt32() == 1;
366     case BitAnd:
367         return child(1)->isInt32(1)
368             || (child(0)->returnsBool() && child(1)->hasInt() && child(1)->asInt() & 1);
369     case Equal:
370     case NotEqual:
371     case LessThan:
372     case GreaterThan:
373     case LessEqual:
374     case GreaterEqual:
375     case Above:
376     case Below:
377     case AboveEqual:
378     case BelowEqual:
379     case EqualOrUnordered:
380         return true;
381     case Phi:
382         // FIXME: We should have a story here.
383         // https://bugs.webkit.org/show_bug.cgi?id=150725
384         return false;
385     default:
386         return false;
387     }
388 }
389
390 TriState Value::asTriState() const
391 {
392     switch (opcode()) {
393     case Const32:
394         return triState(!!asInt32());
395     case Const64:
396         return triState(!!asInt64());
397     case ConstDouble:
398         // Use "!= 0" to really emphasize what this mean with respect to NaN and such.
399         return triState(asDouble() != 0);
400     case ConstFloat:
401         return triState(asFloat() != 0.);
402     default:
403         return MixedTriState;
404     }
405 }
406
407 Effects Value::effects() const
408 {
409     Effects result;
410     switch (opcode()) {
411     case Nop:
412     case Identity:
413     case Const32:
414     case Const64:
415     case ConstDouble:
416     case ConstFloat:
417     case SlotBase:
418     case ArgumentReg:
419     case FramePointer:
420     case Add:
421     case Sub:
422     case Mul:
423     case Neg:
424     case ChillDiv:
425     case ChillMod:
426     case BitAnd:
427     case BitOr:
428     case BitXor:
429     case Shl:
430     case SShr:
431     case ZShr:
432     case Clz:
433     case Abs:
434     case Ceil:
435     case Sqrt:
436     case BitwiseCast:
437     case SExt8:
438     case SExt16:
439     case SExt32:
440     case ZExt32:
441     case Trunc:
442     case IToD:
443     case FloatToDouble:
444     case DoubleToFloat:
445     case Equal:
446     case NotEqual:
447     case LessThan:
448     case GreaterThan:
449     case LessEqual:
450     case GreaterEqual:
451     case Above:
452     case Below:
453     case AboveEqual:
454     case BelowEqual:
455     case EqualOrUnordered:
456     case Select:
457         break;
458     case Div:
459     case Mod:
460         result.controlDependent = true;
461         break;
462     case Load8Z:
463     case Load8S:
464     case Load16Z:
465     case Load16S:
466     case Load:
467         result.reads = as<MemoryValue>()->range();
468         result.controlDependent = true;
469         break;
470     case Store8:
471     case Store16:
472     case Store:
473         result.writes = as<MemoryValue>()->range();
474         result.controlDependent = true;
475         break;
476     case CCall:
477         result = as<CCallValue>()->effects;
478         break;
479     case Patchpoint:
480         result = as<PatchpointValue>()->effects;
481         break;
482     case CheckAdd:
483     case CheckSub:
484     case CheckMul:
485     case Check:
486         result.exitsSideways = true;
487         // The program could read anything after exiting, and it's on us to declare this.
488         result.reads = HeapRange::top();
489         break;
490     case Upsilon:
491     case Set:
492         result.writesLocalState = true;
493         break;
494     case Phi:
495     case Get:
496         result.readsLocalState = true;
497         break;
498     case Jump:
499     case Branch:
500     case Switch:
501     case Return:
502     case Oops:
503         result.terminal = true;
504         break;
505     }
506     return result;
507 }
508
509 ValueKey Value::key() const
510 {
511     switch (opcode()) {
512     case FramePointer:
513         return ValueKey(opcode(), type());
514     case Identity:
515     case Abs:
516     case Ceil:
517     case Sqrt:
518     case SExt8:
519     case SExt16:
520     case SExt32:
521     case ZExt32:
522     case Clz:
523     case Trunc:
524     case IToD:
525     case FloatToDouble:
526     case DoubleToFloat:
527     case Check:
528     case BitwiseCast:
529     case Neg:
530         return ValueKey(opcode(), type(), child(0));
531     case Add:
532     case Sub:
533     case Mul:
534     case Div:
535     case Mod:
536     case ChillDiv:
537     case ChillMod:
538     case BitAnd:
539     case BitOr:
540     case BitXor:
541     case Shl:
542     case SShr:
543     case ZShr:
544     case Equal:
545     case NotEqual:
546     case LessThan:
547     case GreaterThan:
548     case Above:
549     case Below:
550     case AboveEqual:
551     case BelowEqual:
552     case EqualOrUnordered:
553     case CheckAdd:
554     case CheckSub:
555     case CheckMul:
556         return ValueKey(opcode(), type(), child(0), child(1));
557     case Select:
558         return ValueKey(opcode(), type(), child(0), child(1), child(2));
559     case Const32:
560         return ValueKey(Const32, type(), static_cast<int64_t>(asInt32()));
561     case Const64:
562         return ValueKey(Const64, type(), asInt64());
563     case ConstDouble:
564         return ValueKey(ConstDouble, type(), asDouble());
565     case ConstFloat:
566         return ValueKey(ConstFloat, type(), asFloat());
567     case ArgumentReg:
568         return ValueKey(
569             ArgumentReg, type(),
570             static_cast<int64_t>(as<ArgumentRegValue>()->argumentReg().index()));
571     case SlotBase:
572         return ValueKey(
573             SlotBase, type(),
574             static_cast<int64_t>(as<SlotBaseValue>()->slot()->index()));
575     default:
576         return ValueKey();
577     }
578 }
579
580 void Value::performSubstitution()
581 {
582     for (Value*& child : children()) {
583         while (child->opcode() == Identity)
584             child = child->child(0);
585     }
586 }
587
588 void Value::dumpMeta(CommaPrinter&, PrintStream&) const
589 {
590 }
591
592 #if !ASSERT_DISABLED
593 void Value::checkOpcode(Opcode opcode)
594 {
595     ASSERT(!ArgumentRegValue::accepts(opcode));
596     ASSERT(!CCallValue::accepts(opcode));
597     ASSERT(!CheckValue::accepts(opcode));
598     ASSERT(!Const32Value::accepts(opcode));
599     ASSERT(!Const64Value::accepts(opcode));
600     ASSERT(!ConstDoubleValue::accepts(opcode));
601     ASSERT(!ConstFloatValue::accepts(opcode));
602     ASSERT(!ControlValue::accepts(opcode));
603     ASSERT(!MemoryValue::accepts(opcode));
604     ASSERT(!PatchpointValue::accepts(opcode));
605     ASSERT(!SlotBaseValue::accepts(opcode));
606     ASSERT(!UpsilonValue::accepts(opcode));
607     ASSERT(!VariableValue::accepts(opcode));
608 }
609 #endif // !ASSERT_DISABLED
610
611 Type Value::typeFor(Opcode opcode, Value* firstChild, Value* secondChild)
612 {
613     switch (opcode) {
614     case Identity:
615     case Add:
616     case Sub:
617     case Mul:
618     case Div:
619     case Mod:
620     case Neg:
621     case ChillDiv:
622     case ChillMod:
623     case BitAnd:
624     case BitOr:
625     case BitXor:
626     case Shl:
627     case SShr:
628     case ZShr:
629     case Clz:
630     case Abs:
631     case Ceil:
632     case Sqrt:
633     case CheckAdd:
634     case CheckSub:
635     case CheckMul:
636         return firstChild->type();
637     case FramePointer:
638         return pointerType();
639     case SExt8:
640     case SExt16:
641     case Trunc:
642     case Equal:
643     case NotEqual:
644     case LessThan:
645     case GreaterThan:
646     case LessEqual:
647     case GreaterEqual:
648     case Above:
649     case Below:
650     case AboveEqual:
651     case BelowEqual:
652     case EqualOrUnordered:
653         return Int32;
654     case SExt32:
655     case ZExt32:
656         return Int64;
657     case FloatToDouble:
658     case IToD:
659         return Double;
660     case DoubleToFloat:
661         return Float;
662     case BitwiseCast:
663         switch (firstChild->type()) {
664         case Int64:
665             return Double;
666         case Double:
667             return Int64;
668         case Int32:
669             return Float;
670         case Float:
671             return Int32;
672         case Void:
673             ASSERT_NOT_REACHED();
674         }
675         return Void;
676     case Nop:
677         return Void;
678     case Select:
679         ASSERT(secondChild);
680         return secondChild->type();
681     default:
682         RELEASE_ASSERT_NOT_REACHED();
683     }
684 }
685
686 } } // namespace JSC::B3
687
688 #endif // ENABLE(B3_JIT)