e351c55418c0249100e6fb7a68c3341e7fcd4a73
[WebKit-https.git] / Source / JavaScriptCore / runtime / CommonSlowPaths.cpp
1 /*
2  * Copyright (C) 2011, 2012, 2013 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 "CommonSlowPaths.h"
28
29 #if ENABLE(JIT) || ENABLE(LLINT)
30
31 #include "Arguments.h"
32 #include "ArrayConstructor.h"
33 #include "CallFrame.h"
34 #include "CodeProfiling.h"
35 #include "CommonSlowPathsExceptions.h"
36 #include "GetterSetter.h"
37 #include "HostCallReturnValue.h"
38 #include "Interpreter.h"
39 #include "JIT.h"
40 #include "JITDriver.h"
41 #include "JITStubs.h"
42 #include "JSActivation.h"
43 #include "JSCJSValue.h"
44 #include "JSGlobalObjectFunctions.h"
45 #include "JSNameScope.h"
46 #include "JSPropertyNameIterator.h"
47 #include "JSString.h"
48 #include "JSWithScope.h"
49 #include "LLIntCommon.h"
50 #include "LLIntExceptions.h"
51 #include "LowLevelInterpreter.h"
52 #include "ObjectConstructor.h"
53 #include "Operations.h"
54 #include "StructureRareDataInlines.h"
55 #include <wtf/StringPrintStream.h>
56
57 namespace JSC {
58
59 #define BEGIN_NO_SET_PC() \
60     VM& vm = exec->vm();      \
61     NativeCallFrameTracer tracer(&vm, exec)
62
63 #ifndef NDEBUG
64 #define SET_PC_FOR_STUBS() do { \
65         exec->codeBlock()->bytecodeOffset(pc); \
66         exec->setCurrentVPC(pc + 1); \
67     } while (false)
68 #else
69 #define SET_PC_FOR_STUBS() do { \
70         exec->setCurrentVPC(pc + 1); \
71     } while (false)
72 #endif
73
74 #if ENABLE(LLINT)
75 #define RETURN_TO_THROW(exec, pc)   pc = LLInt::returnToThrow(exec, pc)
76 #else
77 #define RETURN_TO_THROW(exec, pc)
78 #endif
79
80 #define BEGIN()                           \
81     BEGIN_NO_SET_PC();                    \
82     SET_PC_FOR_STUBS()
83
84 #define OP(index) (exec->uncheckedR(pc[index].u.operand))
85 #define OP_C(index) (exec->r(pc[index].u.operand))
86
87 #define RETURN_TWO(first, second) do {       \
88         return encodeResult(first, second);        \
89     } while (false)
90
91 #define END_IMPL() RETURN_TWO(pc, exec)
92
93 #define THROW(exceptionToThrow) do {                        \
94         vm.throwException(exec, exceptionToThrow);          \
95         RETURN_TO_THROW(exec, pc);                          \
96         END_IMPL();                                         \
97     } while (false)
98
99 #define CHECK_EXCEPTION() do {                    \
100         if (UNLIKELY(vm.exception())) {           \
101             RETURN_TO_THROW(exec, pc);               \
102             END_IMPL();                           \
103         }                                               \
104     } while (false)
105
106 #define END() do {                        \
107         CHECK_EXCEPTION();                \
108         END_IMPL();                       \
109     } while (false)
110
111 #define BRANCH(opcode, condition) do {                      \
112         bool bCondition = (condition);                         \
113         CHECK_EXCEPTION();                                  \
114         if (bCondition)                                        \
115             pc += pc[OPCODE_LENGTH(opcode) - 1].u.operand;        \
116         else                                                      \
117             pc += OPCODE_LENGTH(opcode);                          \
118         END_IMPL();                                         \
119     } while (false)
120
121 #define RETURN(value) do {                \
122         JSValue rReturnValue = (value);      \
123         CHECK_EXCEPTION();                \
124         OP(1) = rReturnValue;          \
125         END_IMPL();                       \
126     } while (false)
127
128 #if ENABLE(VALUE_PROFILER)
129 #define RETURN_PROFILED(opcode, value) do {               \
130         JSValue rpPeturnValue = (value);                     \
131         CHECK_EXCEPTION();                                \
132         OP(1) = rpPeturnValue;                         \
133         PROFILE_VALUE(opcode, rpPeturnValue);          \
134         END_IMPL();                                       \
135     } while (false)
136
137 #define PROFILE_VALUE(opcode, value) do { \
138         pc[OPCODE_LENGTH(opcode) - 1].u.profile->m_buckets[0] = \
139         JSValue::encode(value);                  \
140     } while (false)
141
142 #else // ENABLE(VALUE_PROFILER)
143 #define RETURN_PROFILED(opcode, value) RETURN(value)
144
145 #define PROFILE_VALUE(opcode, value) do { } while (false)
146
147 #endif // ENABLE(VALUE_PROFILER)
148
149 #define CALL_END_IMPL(exec, callTarget) RETURN_TWO((callTarget), (exec))
150
151 #define CALL_THROW(exec, pc, exceptionToThrow) do {               \
152         ExecState* ctExec = (exec);                                  \
153         Instruction* ctPC = (pc);                                    \
154         vm.throwException(exec, exceptionToThrow);                      \
155         CALL_END_IMPL(ctExec, LLInt::callToThrow(ctExec, ctPC)); \
156     } while (false)
157
158 #define CALL_CHECK_EXCEPTION(exec, pc) do {                       \
159         ExecState* cceExec = (exec);                                 \
160         Instruction* ccePC = (pc);                                   \
161         if (UNLIKELY(vm.exception()))                              \
162             CALL_END_IMPL(cceExec, LLInt::callToThrow(cceExec, ccePC)); \
163     } while (false)
164
165 #define CALL_RETURN(exec, pc, callTarget) do {                    \
166         ExecState* crExec = (exec);                                  \
167         Instruction* crPC = (pc);                                    \
168         void* crCallTarget = (callTarget);                           \
169         CALL_CHECK_EXCEPTION(crExec->callerFrame(), crPC);  \
170         CALL_END_IMPL(crExec, crCallTarget);                \
171     } while (false)
172
173 SLOW_PATH_DECL(slow_path_call_arityCheck)
174 {
175     BEGIN();
176     int SlotsToAdd = CommonSlowPaths::arityCheckFor(exec, &vm.interpreter->stack(), CodeForCall);
177     if (SlotsToAdd < 0) {
178         ReturnAddressPtr returnPC = exec->returnPC();
179         exec = exec->callerFrame();
180         CommonSlowPaths::interpreterThrowInCaller(exec, returnPC, createStackOverflowError(exec));
181         RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
182     }
183     RETURN_TWO(0, reinterpret_cast<ExecState*>(SlotsToAdd));
184 }
185
186 SLOW_PATH_DECL(slow_path_construct_arityCheck)
187 {
188     BEGIN();
189     int SlotsToAdd = CommonSlowPaths::arityCheckFor(exec, &vm.interpreter->stack(), CodeForConstruct);
190     if (SlotsToAdd < 0) {
191         ReturnAddressPtr returnPC = exec->returnPC();
192         exec = exec->callerFrame();
193         CommonSlowPaths::interpreterThrowInCaller(exec, returnPC, createStackOverflowError(exec));
194         RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
195     }
196     RETURN_TWO(0, reinterpret_cast<ExecState*>(SlotsToAdd));
197 }
198
199 SLOW_PATH_DECL(slow_path_create_arguments)
200 {
201     BEGIN();
202     JSValue arguments = JSValue(Arguments::create(vm, exec));
203     CHECK_EXCEPTION();
204     exec->uncheckedR(pc[1].u.operand) = arguments;
205     exec->uncheckedR(unmodifiedArgumentsRegister(pc[1].u.operand)) = arguments;
206     END();
207 }
208
209 SLOW_PATH_DECL(slow_path_create_this)
210 {
211     BEGIN();
212     JSFunction* constructor = jsCast<JSFunction*>(OP(2).jsValue().asCell());
213     
214 #if !ASSERT_DISABLED
215     ConstructData constructData;
216     ASSERT(constructor->methodTable()->getConstructData(constructor, constructData) == ConstructTypeJS);
217 #endif
218
219     size_t inlineCapacity = pc[3].u.operand;
220     Structure* structure = constructor->allocationProfile(exec, inlineCapacity)->structure();
221     RETURN(constructEmptyObject(exec, structure));
222 }
223
224 SLOW_PATH_DECL(slow_path_to_this)
225 {
226     BEGIN();
227     JSValue v1 = OP(1).jsValue();
228 #if ENABLE(VALUE_PROFILER)
229     pc[OPCODE_LENGTH(op_to_this) - 1].u.profile->m_buckets[0] =
230         JSValue::encode(v1.structureOrUndefined());
231 #endif
232     RETURN(v1.toThis(exec, exec->codeBlock()->isStrictMode() ? StrictMode : NotStrictMode));
233 }
234
235 SLOW_PATH_DECL(slow_path_not)
236 {
237     BEGIN();
238     RETURN(jsBoolean(!OP_C(2).jsValue().toBoolean(exec)));
239 }
240
241 SLOW_PATH_DECL(slow_path_eq)
242 {
243     BEGIN();
244     RETURN(jsBoolean(JSValue::equal(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
245 }
246
247 SLOW_PATH_DECL(slow_path_neq)
248 {
249     BEGIN();
250     RETURN(jsBoolean(!JSValue::equal(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
251 }
252
253 SLOW_PATH_DECL(slow_path_stricteq)
254 {
255     BEGIN();
256     RETURN(jsBoolean(JSValue::strictEqual(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
257 }
258
259 SLOW_PATH_DECL(slow_path_nstricteq)
260 {
261     BEGIN();
262     RETURN(jsBoolean(!JSValue::strictEqual(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
263 }
264
265 SLOW_PATH_DECL(slow_path_less)
266 {
267     BEGIN();
268     RETURN(jsBoolean(jsLess<true>(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
269 }
270
271 SLOW_PATH_DECL(slow_path_lesseq)
272 {
273     BEGIN();
274     RETURN(jsBoolean(jsLessEq<true>(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
275 }
276
277 SLOW_PATH_DECL(slow_path_greater)
278 {
279     BEGIN();
280     RETURN(jsBoolean(jsLess<false>(exec, OP_C(3).jsValue(), OP_C(2).jsValue())));
281 }
282
283 SLOW_PATH_DECL(slow_path_greatereq)
284 {
285     BEGIN();
286     RETURN(jsBoolean(jsLessEq<false>(exec, OP_C(3).jsValue(), OP_C(2).jsValue())));
287 }
288
289 SLOW_PATH_DECL(slow_path_inc)
290 {
291     BEGIN();
292     RETURN(jsNumber(OP(1).jsValue().toNumber(exec) + 1));
293 }
294
295 SLOW_PATH_DECL(slow_path_dec)
296 {
297     BEGIN();
298     RETURN(jsNumber(OP(1).jsValue().toNumber(exec) - 1));
299 }
300
301 SLOW_PATH_DECL(slow_path_to_number)
302 {
303     BEGIN();
304     RETURN(jsNumber(OP_C(2).jsValue().toNumber(exec)));
305 }
306
307 SLOW_PATH_DECL(slow_path_negate)
308 {
309     BEGIN();
310     RETURN(jsNumber(-OP_C(2).jsValue().toNumber(exec)));
311 }
312
313 SLOW_PATH_DECL(slow_path_add)
314 {
315     BEGIN();
316     JSValue v1 = OP_C(2).jsValue();
317     JSValue v2 = OP_C(3).jsValue();
318     
319     if (v1.isString() && !v2.isObject())
320         RETURN(jsString(exec, asString(v1), v2.toString(exec)));
321     
322     if (v1.isNumber() && v2.isNumber())
323         RETURN(jsNumber(v1.asNumber() + v2.asNumber()));
324     
325     RETURN(jsAddSlowCase(exec, v1, v2));
326 }
327
328 // The following arithmetic and bitwise operations need to be sure to run
329 // toNumber() on their operands in order.  (A call to toNumber() is idempotent
330 // if an exception is already set on the ExecState.)
331
332 SLOW_PATH_DECL(slow_path_mul)
333 {
334     BEGIN();
335     double a = OP_C(2).jsValue().toNumber(exec);
336     double b = OP_C(3).jsValue().toNumber(exec);
337     RETURN(jsNumber(a * b));
338 }
339
340 SLOW_PATH_DECL(slow_path_sub)
341 {
342     BEGIN();
343     double a = OP_C(2).jsValue().toNumber(exec);
344     double b = OP_C(3).jsValue().toNumber(exec);
345     RETURN(jsNumber(a - b));
346 }
347
348 SLOW_PATH_DECL(slow_path_div)
349 {
350     BEGIN();
351     double a = OP_C(2).jsValue().toNumber(exec);
352     double b = OP_C(3).jsValue().toNumber(exec);
353     RETURN(jsNumber(a / b));
354 }
355
356 SLOW_PATH_DECL(slow_path_mod)
357 {
358     BEGIN();
359     double a = OP_C(2).jsValue().toNumber(exec);
360     double b = OP_C(3).jsValue().toNumber(exec);
361     RETURN(jsNumber(fmod(a, b)));
362 }
363
364 SLOW_PATH_DECL(slow_path_lshift)
365 {
366     BEGIN();
367     int32_t a = OP_C(2).jsValue().toInt32(exec);
368     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
369     RETURN(jsNumber(a << (b & 31)));
370 }
371
372 SLOW_PATH_DECL(slow_path_rshift)
373 {
374     BEGIN();
375     int32_t a = OP_C(2).jsValue().toInt32(exec);
376     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
377     RETURN(jsNumber(a >> (b & 31)));
378 }
379
380 SLOW_PATH_DECL(slow_path_urshift)
381 {
382     BEGIN();
383     uint32_t a = OP_C(2).jsValue().toUInt32(exec);
384     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
385     RETURN(jsNumber(a >> (b & 31)));
386 }
387
388 SLOW_PATH_DECL(slow_path_bitand)
389 {
390     BEGIN();
391     int32_t a = OP_C(2).jsValue().toInt32(exec);
392     int32_t b = OP_C(3).jsValue().toInt32(exec);
393     RETURN(jsNumber(a & b));
394 }
395
396 SLOW_PATH_DECL(slow_path_bitor)
397 {
398     BEGIN();
399     int32_t a = OP_C(2).jsValue().toInt32(exec);
400     int32_t b = OP_C(3).jsValue().toInt32(exec);
401     RETURN(jsNumber(a | b));
402 }
403
404 SLOW_PATH_DECL(slow_path_bitxor)
405 {
406     BEGIN();
407     int32_t a = OP_C(2).jsValue().toInt32(exec);
408     int32_t b = OP_C(3).jsValue().toInt32(exec);
409     RETURN(jsNumber(a ^ b));
410 }
411
412 SLOW_PATH_DECL(slow_path_typeof)
413 {
414     BEGIN();
415     RETURN(jsTypeStringForValue(exec, OP_C(2).jsValue()));
416 }
417
418 SLOW_PATH_DECL(slow_path_is_object)
419 {
420     BEGIN();
421     RETURN(jsBoolean(jsIsObjectType(exec, OP_C(2).jsValue())));
422 }
423
424 SLOW_PATH_DECL(slow_path_is_function)
425 {
426     BEGIN();
427     RETURN(jsBoolean(jsIsFunctionType(OP_C(2).jsValue())));
428 }
429
430 SLOW_PATH_DECL(slow_path_in)
431 {
432     BEGIN();
433     RETURN(jsBoolean(CommonSlowPaths::opIn(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
434 }
435
436 SLOW_PATH_DECL(slow_path_del_by_val)
437 {
438     BEGIN();
439     JSValue baseValue = OP_C(2).jsValue();
440     JSObject* baseObject = baseValue.toObject(exec);
441     
442     JSValue subscript = OP_C(3).jsValue();
443     
444     bool couldDelete;
445     
446     uint32_t i;
447     if (subscript.getUInt32(i))
448         couldDelete = baseObject->methodTable()->deletePropertyByIndex(baseObject, exec, i);
449     else if (isName(subscript))
450         couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, jsCast<NameInstance*>(subscript.asCell())->privateName());
451     else {
452         CHECK_EXCEPTION();
453         Identifier property(exec, subscript.toString(exec)->value(exec));
454         CHECK_EXCEPTION();
455         couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, property);
456     }
457     
458     if (!couldDelete && exec->codeBlock()->isStrictMode())
459         THROW(createTypeError(exec, "Unable to delete property."));
460     
461     RETURN(jsBoolean(couldDelete));
462 }
463
464 SLOW_PATH_DECL(slow_path_strcat)
465 {
466     BEGIN();
467     RETURN(jsString(exec, &OP(2), pc[3].u.operand));
468 }
469
470 SLOW_PATH_DECL(slow_path_to_primitive)
471 {
472     BEGIN();
473     RETURN(OP_C(2).jsValue().toPrimitive(exec));
474 }
475
476 } // namespace JSC
477
478 #endif // ENABLE(JIT) || ENABLE(LLINT)