2 * Copyright (C) 2011 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 "DFGOperations.h"
31 #include "CodeBlock.h"
32 #include "Interpreter.h"
33 #include "JSByteArray.h"
34 #include "JSGlobalData.h"
35 #include "Operations.h"
37 namespace JSC
{ namespace DFG
{
39 EncodedJSValue
operationConvertThis(ExecState
* exec
, EncodedJSValue encodedOp
)
41 return JSValue::encode(JSValue::decode(encodedOp
).toThisObject(exec
));
44 EncodedJSValue
operationValueAdd(ExecState
* exec
, EncodedJSValue encodedOp1
, EncodedJSValue encodedOp2
)
46 JSValue op1
= JSValue::decode(encodedOp1
);
47 JSValue op2
= JSValue::decode(encodedOp2
);
49 if (op1
.isInt32() && op2
.isInt32()) {
50 int64_t result64
= static_cast<int64_t>(op1
.asInt32()) + static_cast<int64_t>(op2
.asInt32());
51 int32_t result32
= static_cast<int32_t>(result64
);
52 if (LIKELY(result32
== result64
))
53 return JSValue::encode(jsNumber(result32
));
54 return JSValue::encode(jsNumber((double)result64
));
59 if (op1
.getNumber(number1
) && op2
.getNumber(number2
))
60 return JSValue::encode(jsNumber(number1
+ number2
));
62 return JSValue::encode(jsAddSlowCase(exec
, op1
, op2
));
65 EncodedJSValue
operationGetByVal(ExecState
* exec
, EncodedJSValue encodedBase
, EncodedJSValue encodedProperty
)
67 JSValue baseValue
= JSValue::decode(encodedBase
);
68 JSValue property
= JSValue::decode(encodedProperty
);
70 if (LIKELY(baseValue
.isCell())) {
71 JSCell
* base
= baseValue
.asCell();
73 if (property
.isUInt32()) {
74 JSGlobalData
* globalData
= &exec
->globalData();
75 uint32_t i
= property
.asUInt32();
77 // FIXME: the JIT used to handle these in compiled code!
78 if (isJSArray(globalData
, base
) && asArray(base
)->canGetIndex(i
))
79 return JSValue::encode(asArray(base
)->getIndex(i
));
81 // FIXME: the JITstub used to relink this to an optimized form!
82 if (isJSString(globalData
, base
) && asString(base
)->canGetIndex(i
))
83 return JSValue::encode(asString(base
)->getIndex(exec
, i
));
85 // FIXME: the JITstub used to relink this to an optimized form!
86 if (isJSByteArray(globalData
, base
) && asByteArray(base
)->canAccessIndex(i
))
87 return JSValue::encode(asByteArray(base
)->getIndex(exec
, i
));
89 return JSValue::encode(baseValue
.get(exec
, i
));
92 if (property
.isString()) {
93 Identifier
propertyName(exec
, asString(property
)->value(exec
));
94 PropertySlot
slot(base
);
95 if (base
->fastGetOwnPropertySlot(exec
, propertyName
, slot
))
96 return JSValue::encode(slot
.getValue(exec
, propertyName
));
100 Identifier
ident(exec
, property
.toString(exec
));
101 return JSValue::encode(baseValue
.get(exec
, ident
));
104 EncodedJSValue
operationGetById(ExecState
* exec
, EncodedJSValue encodedBase
, Identifier
* identifier
)
106 JSValue baseValue
= JSValue::decode(encodedBase
);
107 PropertySlot
slot(baseValue
);
108 return JSValue::encode(baseValue
.get(exec
, *identifier
, slot
));
111 template<bool strict
>
112 ALWAYS_INLINE
static void operationPutByValInternal(ExecState
* exec
, EncodedJSValue encodedBase
, EncodedJSValue encodedProperty
, EncodedJSValue encodedValue
)
114 JSGlobalData
* globalData
= &exec
->globalData();
116 JSValue baseValue
= JSValue::decode(encodedBase
);
117 JSValue property
= JSValue::decode(encodedProperty
);
118 JSValue value
= JSValue::decode(encodedValue
);
120 if (LIKELY(property
.isUInt32())) {
121 uint32_t i
= property
.asUInt32();
123 if (isJSArray(globalData
, baseValue
)) {
124 JSArray
* jsArray
= asArray(baseValue
);
125 if (jsArray
->canSetIndex(i
)) {
126 jsArray
->setIndex(*globalData
, i
, value
);
130 jsArray
->JSArray::put(exec
, i
, value
);
134 if (isJSByteArray(globalData
, baseValue
) && asByteArray(baseValue
)->canAccessIndex(i
)) {
135 JSByteArray
* jsByteArray
= asByteArray(baseValue
);
136 // FIXME: the JITstub used to relink this to an optimized form!
137 if (value
.isInt32()) {
138 jsByteArray
->setIndex(i
, value
.asInt32());
143 if (value
.getNumber(dValue
)) {
144 jsByteArray
->setIndex(i
, dValue
);
149 baseValue
.put(exec
, i
, value
);
153 // Don't put to an object if toString throws an exception.
154 Identifier
ident(exec
, property
.toString(exec
));
155 if (!globalData
->exception
) {
156 PutPropertySlot
slot(strict
);
157 baseValue
.put(exec
, ident
, value
, slot
);
161 void operationPutByValStrict(ExecState
* exec
, EncodedJSValue encodedBase
, EncodedJSValue encodedProperty
, EncodedJSValue encodedValue
)
163 operationPutByValInternal
<true>(exec
, encodedBase
, encodedProperty
, encodedValue
);
166 void operationPutByValNonStrict(ExecState
* exec
, EncodedJSValue encodedBase
, EncodedJSValue encodedProperty
, EncodedJSValue encodedValue
)
168 operationPutByValInternal
<false>(exec
, encodedBase
, encodedProperty
, encodedValue
);
171 void operationPutByIdStrict(ExecState
* exec
, EncodedJSValue encodedValue
, EncodedJSValue encodedBase
, Identifier
* identifier
)
173 PutPropertySlot
slot(true);
174 JSValue::decode(encodedBase
).put(exec
, *identifier
, JSValue::decode(encodedValue
), slot
);
177 void operationPutByIdNonStrict(ExecState
* exec
, EncodedJSValue encodedValue
, EncodedJSValue encodedBase
, Identifier
* identifier
)
179 PutPropertySlot
slot(false);
180 JSValue::decode(encodedBase
).put(exec
, *identifier
, JSValue::decode(encodedValue
), slot
);
183 void operationPutByIdDirectStrict(ExecState
* exec
, EncodedJSValue encodedValue
, EncodedJSValue encodedBase
, Identifier
* identifier
)
185 PutPropertySlot
slot(true);
186 JSValue::decode(encodedBase
).putDirect(exec
, *identifier
, JSValue::decode(encodedValue
), slot
);
189 void operationPutByIdDirectNonStrict(ExecState
* exec
, EncodedJSValue encodedValue
, EncodedJSValue encodedBase
, Identifier
* identifier
)
191 PutPropertySlot
slot(false);
192 JSValue::decode(encodedBase
).putDirect(exec
, *identifier
, JSValue::decode(encodedValue
), slot
);
195 bool operationCompareLess(ExecState
* exec
, EncodedJSValue encodedOp1
, EncodedJSValue encodedOp2
)
197 return jsLess(exec
, JSValue::decode(encodedOp1
), JSValue::decode(encodedOp2
));
200 bool operationCompareLessEq(ExecState
* exec
, EncodedJSValue encodedOp1
, EncodedJSValue encodedOp2
)
202 return jsLessEq(exec
, JSValue::decode(encodedOp1
), JSValue::decode(encodedOp2
));
205 bool operationCompareEq(ExecState
* exec
, EncodedJSValue encodedOp1
, EncodedJSValue encodedOp2
)
207 return JSValue::equal(exec
, JSValue::decode(encodedOp1
), JSValue::decode(encodedOp2
));
210 bool operationCompareStrictEq(ExecState
* exec
, EncodedJSValue encodedOp1
, EncodedJSValue encodedOp2
)
212 return JSValue::strictEqual(exec
, JSValue::decode(encodedOp1
), JSValue::decode(encodedOp2
));
215 DFGHandler
lookupExceptionHandler(ExecState
* exec
, ReturnAddressPtr faultLocation
)
217 JSValue exceptionValue
= exec
->exception();
218 ASSERT(exceptionValue
);
220 unsigned vPCIndex
= exec
->codeBlock()->bytecodeOffset(faultLocation
);
221 HandlerInfo
* handler
= exec
->globalData().interpreter
->throwException(exec
, exceptionValue
, vPCIndex
);
223 void* catchRoutine
= handler
? handler
->nativeCode
.executableAddress() : (void*)ctiOpThrowNotCaught
;
224 ASSERT(catchRoutine
);
225 return DFGHandler(exec
, catchRoutine
);
228 double dfgConvertJSValueToNumber(ExecState
* exec
, EncodedJSValue value
)
230 return JSValue::decode(value
).toNumber(exec
);
233 int32_t dfgConvertJSValueToInt32(ExecState
* exec
, EncodedJSValue value
)
235 return JSValue::decode(value
).toInt32(exec
);
238 bool dfgConvertJSValueToBoolean(ExecState
* exec
, EncodedJSValue encodedOp
)
240 return JSValue::decode(encodedOp
).toBoolean(exec
);
243 } } // namespace JSC::DFG