]> git.saurik.com Git - apple/javascriptcore.git/blob - dfg/DFGOperations.cpp
JavaScriptCore-903.5.tar.gz
[apple/javascriptcore.git] / dfg / DFGOperations.cpp
1 /*
2 * Copyright (C) 2011 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 "DFGOperations.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "CodeBlock.h"
32 #include "Interpreter.h"
33 #include "JSByteArray.h"
34 #include "JSGlobalData.h"
35 #include "Operations.h"
36
37 namespace JSC { namespace DFG {
38
39 EncodedJSValue operationConvertThis(ExecState* exec, EncodedJSValue encodedOp)
40 {
41 return JSValue::encode(JSValue::decode(encodedOp).toThisObject(exec));
42 }
43
44 EncodedJSValue operationValueAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
45 {
46 JSValue op1 = JSValue::decode(encodedOp1);
47 JSValue op2 = JSValue::decode(encodedOp2);
48
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));
55 }
56
57 double number1;
58 double number2;
59 if (op1.getNumber(number1) && op2.getNumber(number2))
60 return JSValue::encode(jsNumber(number1 + number2));
61
62 return JSValue::encode(jsAddSlowCase(exec, op1, op2));
63 }
64
65 EncodedJSValue operationGetByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty)
66 {
67 JSValue baseValue = JSValue::decode(encodedBase);
68 JSValue property = JSValue::decode(encodedProperty);
69
70 if (LIKELY(baseValue.isCell())) {
71 JSCell* base = baseValue.asCell();
72
73 if (property.isUInt32()) {
74 JSGlobalData* globalData = &exec->globalData();
75 uint32_t i = property.asUInt32();
76
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));
80
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));
84
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));
88
89 return JSValue::encode(baseValue.get(exec, i));
90 }
91
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));
97 }
98 }
99
100 Identifier ident(exec, property.toString(exec));
101 return JSValue::encode(baseValue.get(exec, ident));
102 }
103
104 EncodedJSValue operationGetById(ExecState* exec, EncodedJSValue encodedBase, Identifier* identifier)
105 {
106 JSValue baseValue = JSValue::decode(encodedBase);
107 PropertySlot slot(baseValue);
108 return JSValue::encode(baseValue.get(exec, *identifier, slot));
109 }
110
111 template<bool strict>
112 ALWAYS_INLINE static void operationPutByValInternal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
113 {
114 JSGlobalData* globalData = &exec->globalData();
115
116 JSValue baseValue = JSValue::decode(encodedBase);
117 JSValue property = JSValue::decode(encodedProperty);
118 JSValue value = JSValue::decode(encodedValue);
119
120 if (LIKELY(property.isUInt32())) {
121 uint32_t i = property.asUInt32();
122
123 if (isJSArray(globalData, baseValue)) {
124 JSArray* jsArray = asArray(baseValue);
125 if (jsArray->canSetIndex(i)) {
126 jsArray->setIndex(*globalData, i, value);
127 return;
128 }
129
130 jsArray->JSArray::put(exec, i, value);
131 return;
132 }
133
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());
139 return;
140 }
141
142 double dValue = 0;
143 if (value.getNumber(dValue)) {
144 jsByteArray->setIndex(i, dValue);
145 return;
146 }
147 }
148
149 baseValue.put(exec, i, value);
150 return;
151 }
152
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);
158 }
159 }
160
161 void operationPutByValStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
162 {
163 operationPutByValInternal<true>(exec, encodedBase, encodedProperty, encodedValue);
164 }
165
166 void operationPutByValNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
167 {
168 operationPutByValInternal<false>(exec, encodedBase, encodedProperty, encodedValue);
169 }
170
171 void operationPutByIdStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* identifier)
172 {
173 PutPropertySlot slot(true);
174 JSValue::decode(encodedBase).put(exec, *identifier, JSValue::decode(encodedValue), slot);
175 }
176
177 void operationPutByIdNonStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* identifier)
178 {
179 PutPropertySlot slot(false);
180 JSValue::decode(encodedBase).put(exec, *identifier, JSValue::decode(encodedValue), slot);
181 }
182
183 void operationPutByIdDirectStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* identifier)
184 {
185 PutPropertySlot slot(true);
186 JSValue::decode(encodedBase).putDirect(exec, *identifier, JSValue::decode(encodedValue), slot);
187 }
188
189 void operationPutByIdDirectNonStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* identifier)
190 {
191 PutPropertySlot slot(false);
192 JSValue::decode(encodedBase).putDirect(exec, *identifier, JSValue::decode(encodedValue), slot);
193 }
194
195 bool operationCompareLess(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
196 {
197 return jsLess(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
198 }
199
200 bool operationCompareLessEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
201 {
202 return jsLessEq(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
203 }
204
205 bool operationCompareEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
206 {
207 return JSValue::equal(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
208 }
209
210 bool operationCompareStrictEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
211 {
212 return JSValue::strictEqual(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
213 }
214
215 DFGHandler lookupExceptionHandler(ExecState* exec, ReturnAddressPtr faultLocation)
216 {
217 JSValue exceptionValue = exec->exception();
218 ASSERT(exceptionValue);
219
220 unsigned vPCIndex = exec->codeBlock()->bytecodeOffset(faultLocation);
221 HandlerInfo* handler = exec->globalData().interpreter->throwException(exec, exceptionValue, vPCIndex);
222
223 void* catchRoutine = handler ? handler->nativeCode.executableAddress() : (void*)ctiOpThrowNotCaught;
224 ASSERT(catchRoutine);
225 return DFGHandler(exec, catchRoutine);
226 }
227
228 double dfgConvertJSValueToNumber(ExecState* exec, EncodedJSValue value)
229 {
230 return JSValue::decode(value).toNumber(exec);
231 }
232
233 int32_t dfgConvertJSValueToInt32(ExecState* exec, EncodedJSValue value)
234 {
235 return JSValue::decode(value).toInt32(exec);
236 }
237
238 bool dfgConvertJSValueToBoolean(ExecState* exec, EncodedJSValue encodedOp)
239 {
240 return JSValue::decode(encodedOp).toBoolean(exec);
241 }
242
243 } } // namespace JSC::DFG
244
245 #endif