FTL should be able to do polymorphic call inlining
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGLazyJSValue.cpp
1 /*
2  * Copyright (C) 2013, 2014 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 "DFGLazyJSValue.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "JSCInlines.h"
32
33 namespace JSC { namespace DFG {
34
35 JSValue LazyJSValue::getValue(VM& vm) const
36 {
37     switch (m_kind) {
38     case KnownValue:
39         return value()->value();
40     case SingleCharacterString:
41         return jsSingleCharacterString(&vm, u.character);
42     case KnownStringImpl:
43         return jsString(&vm, u.stringImpl);
44     }
45     RELEASE_ASSERT_NOT_REACHED();
46     return JSValue();
47 }
48
49 static TriState equalToSingleCharacter(JSValue value, UChar character)
50 {
51     if (!value.isString())
52         return FalseTriState;
53     
54     JSString* jsString = asString(value);
55     if (jsString->length() != 1)
56         return FalseTriState;
57     
58     const StringImpl* string = jsString->tryGetValueImpl();
59     if (!string)
60         return MixedTriState;
61     
62     return triState(string->at(0) == character);
63 }
64
65 static TriState equalToStringImpl(JSValue value, StringImpl* stringImpl)
66 {
67     if (!value.isString())
68         return FalseTriState;
69     
70     JSString* jsString = asString(value);
71     const StringImpl* string = jsString->tryGetValueImpl();
72     if (!string)
73         return MixedTriState;
74     
75     return triState(WTF::equal(stringImpl, string));
76 }
77
78 TriState LazyJSValue::strictEqual(const LazyJSValue& other) const
79 {
80     switch (m_kind) {
81     case KnownValue:
82         switch (other.m_kind) {
83         case KnownValue:
84             return JSValue::pureStrictEqual(value()->value(), other.value()->value());
85         case SingleCharacterString:
86             return equalToSingleCharacter(value()->value(), other.character());
87         case KnownStringImpl:
88             return equalToStringImpl(value()->value(), other.stringImpl());
89         }
90         break;
91     case SingleCharacterString:
92         switch (other.m_kind) {
93         case SingleCharacterString:
94             return triState(character() == other.character());
95         case KnownStringImpl:
96             if (other.stringImpl()->length() != 1)
97                 return FalseTriState;
98             return triState(other.stringImpl()->at(0) == character());
99         default:
100             return other.strictEqual(*this);
101         }
102         break;
103     case KnownStringImpl:
104         switch (other.m_kind) {
105         case KnownStringImpl:
106             return triState(WTF::equal(stringImpl(), other.stringImpl()));
107         default:
108             return other.strictEqual(*this);
109         }
110         break;
111     }
112     RELEASE_ASSERT_NOT_REACHED();
113     return FalseTriState;
114 }
115
116 uintptr_t LazyJSValue::switchLookupValue(SwitchKind kind) const
117 {
118     // NB. Not every kind of JSValue will be able to give you a switch lookup
119     // value, and this method will assert, or do bad things, if you use it
120     // for a kind of value that can't.
121     switch (m_kind) {
122     case KnownValue:
123         switch (kind) {
124         case SwitchImm:
125             return value()->value().asInt32();
126         case SwitchCell:
127             return bitwise_cast<uintptr_t>(value()->value().asCell());
128         default:
129             RELEASE_ASSERT_NOT_REACHED();
130             return 0;
131         }
132     case SingleCharacterString:
133         switch (kind) {
134         case SwitchChar:
135             return character();
136         default:
137             RELEASE_ASSERT_NOT_REACHED();
138             return 0;
139         }
140     default:
141         RELEASE_ASSERT_NOT_REACHED();
142         return 0;
143     }
144 }
145
146 void LazyJSValue::dumpInContext(PrintStream& out, DumpContext* context) const
147 {
148     switch (m_kind) {
149     case KnownValue:
150         value()->dumpInContext(out, context);
151         return;
152     case SingleCharacterString:
153         out.print("Lazy:SingleCharacterString(");
154         out.printf("%04X", static_cast<unsigned>(character()));
155         out.print(" / ", StringImpl::utf8ForCharacters(&u.character, 1), ")");
156         return;
157     case KnownStringImpl:
158         out.print("Lazy:String(", stringImpl(), ")");
159         return;
160     }
161     RELEASE_ASSERT_NOT_REACHED();
162 }
163
164 void LazyJSValue::dump(PrintStream& out) const
165 {
166     dumpInContext(out, 0);
167 }
168
169 } } // namespace JSC::DFG
170
171 #endif // ENABLE(DFG_JIT)
172