2 * Copyright (C) 2013, 2014, 2016 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "DFGLazyJSValue.h"
31 #include "CCallHelpers.h"
33 #include "JSCInlines.h"
34 #include "LinkBuffer.h"
36 namespace JSC { namespace DFG {
38 LazyJSValue LazyJSValue::newString(Graph& graph, const String& string)
41 result.m_kind = NewStringImpl;
42 result.u.stringImpl = graph.m_localStrings.add(string).iterator->impl();
46 JSValue LazyJSValue::getValue(VM& vm) const
50 return value()->value();
51 case SingleCharacterString:
52 return jsSingleCharacterString(&vm, u.character);
55 return jsString(&vm, u.stringImpl);
57 RELEASE_ASSERT_NOT_REACHED();
61 static TriState equalToSingleCharacter(JSValue value, UChar character)
63 if (!value.isString())
66 JSString* jsString = asString(value);
67 if (jsString->length() != 1)
70 const StringImpl* string = jsString->tryGetValueImpl();
74 return triState(string->at(0) == character);
77 static TriState equalToStringImpl(JSValue value, StringImpl* stringImpl)
79 if (!value.isString())
82 JSString* jsString = asString(value);
83 const StringImpl* string = jsString->tryGetValueImpl();
87 return triState(WTF::equal(stringImpl, string));
90 const StringImpl* LazyJSValue::tryGetStringImpl() const
98 if (JSString* string = value()->dynamicCast<JSString*>())
99 return string->tryGetValueImpl();
107 String LazyJSValue::tryGetString(Graph& graph) const
113 case SingleCharacterString:
114 return String(&u.character, 1);
117 if (const StringImpl* string = tryGetStringImpl()) {
118 unsigned ginormousStringLength = 10000;
119 if (string->length() > ginormousStringLength)
122 auto result = graph.m_copiedStrings.add(string, String());
123 if (result.isNewEntry)
124 result.iterator->value = string->isolatedCopy();
125 return result.iterator->value;
132 TriState LazyJSValue::strictEqual(const LazyJSValue& other) const
136 switch (other.m_kind) {
138 return JSValue::pureStrictEqual(value()->value(), other.value()->value());
139 case SingleCharacterString:
140 return equalToSingleCharacter(value()->value(), other.character());
141 case KnownStringImpl:
143 return equalToStringImpl(value()->value(), other.stringImpl());
146 case SingleCharacterString:
147 switch (other.m_kind) {
148 case SingleCharacterString:
149 return triState(character() == other.character());
150 case KnownStringImpl:
152 if (other.stringImpl()->length() != 1)
153 return FalseTriState;
154 return triState(other.stringImpl()->at(0) == character());
156 return other.strictEqual(*this);
159 case KnownStringImpl:
161 switch (other.m_kind) {
162 case KnownStringImpl:
164 return triState(WTF::equal(stringImpl(), other.stringImpl()));
166 return other.strictEqual(*this);
170 RELEASE_ASSERT_NOT_REACHED();
171 return FalseTriState;
174 uintptr_t LazyJSValue::switchLookupValue(SwitchKind kind) const
176 // NB. Not every kind of JSValue will be able to give you a switch lookup
177 // value, and this method will assert, or do bad things, if you use it
178 // for a kind of value that can't.
183 return value()->value().asInt32();
185 return bitwise_cast<uintptr_t>(value()->value().asCell());
187 RELEASE_ASSERT_NOT_REACHED();
190 case SingleCharacterString:
195 RELEASE_ASSERT_NOT_REACHED();
199 RELEASE_ASSERT_NOT_REACHED();
204 void LazyJSValue::emit(CCallHelpers& jit, JSValueRegs result) const
206 if (m_kind == KnownValue) {
207 jit.moveValue(value()->value(), result);
211 // It must be some kind of cell.
212 #if USE(JSVALUE32_64)
213 jit.move(CCallHelpers::TrustedImm32(JSValue::CellTag), result.tagGPR());
215 CCallHelpers::DataLabelPtr label = jit.moveWithPatch(
216 CCallHelpers::TrustedImmPtr(static_cast<size_t>(0xd1e7beeflu)),
217 result.payloadGPR());
219 LazyJSValue thisValue = *this;
221 // Once we do this, we're committed. Otherwise we leak memory. Note that we call ref/deref
222 // manually to ensure that there is no concurrency shadiness. We are doing something here
223 // that might be rather brutal: transfering ownership of this string.
224 if (m_kind == NewStringImpl)
225 thisValue.u.stringImpl->ref();
227 CodeBlock* codeBlock = jit.codeBlock();
230 [codeBlock, label, thisValue] (LinkBuffer& linkBuffer) {
231 JSValue realValue = thisValue.getValue(linkBuffer.vm());
232 RELEASE_ASSERT(realValue.isCell());
234 codeBlock->addConstant(realValue);
236 if (thisValue.m_kind == NewStringImpl)
237 thisValue.u.stringImpl->deref();
239 linkBuffer.patch(label, realValue.asCell());
243 void LazyJSValue::dumpInContext(PrintStream& out, DumpContext* context) const
247 value()->dumpInContext(out, context);
249 case SingleCharacterString:
250 out.print("Lazy:SingleCharacterString(");
251 out.printf("%04X", static_cast<unsigned>(character()));
252 out.print(" / ", StringImpl::utf8ForCharacters(&u.character, 1), ")");
254 case KnownStringImpl:
255 out.print("Lazy:KnownString(", stringImpl(), ")");
258 out.print("Lazy:NewString(", stringImpl(), ")");
261 RELEASE_ASSERT_NOT_REACHED();
264 void LazyJSValue::dump(PrintStream& out) const
266 dumpInContext(out, 0);
269 } } // namespace JSC::DFG
271 #endif // ENABLE(DFG_JIT)