201d4deab437c3cbf1d052ec45fb3b65b10b83ab
[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.exception = (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.exception = (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         vm.exception = createStackOverflowError(exec);
181         CommonSlowPaths::interpreterThrowInCaller(exec, returnPC);
182         RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
183     }
184     RETURN_TWO(0, reinterpret_cast<ExecState*>(SlotsToAdd));
185 }
186
187 SLOW_PATH_DECL(slow_path_construct_arityCheck)
188 {
189     BEGIN();
190     int SlotsToAdd = CommonSlowPaths::arityCheckFor(exec, &vm.interpreter->stack(), CodeForConstruct);
191     if (SlotsToAdd < 0) {
192         ReturnAddressPtr returnPC = exec->returnPC();
193         exec = exec->callerFrame();
194         vm.exception = createStackOverflowError(exec);
195         CommonSlowPaths::interpreterThrowInCaller(exec, returnPC);
196         RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
197     }
198     RETURN_TWO(0, reinterpret_cast<ExecState*>(SlotsToAdd));
199 }
200
201 SLOW_PATH_DECL(slow_path_create_arguments)
202 {
203     BEGIN();
204     JSValue arguments = JSValue(Arguments::create(vm, exec));
205     CHECK_EXCEPTION();
206     exec->uncheckedR(pc[1].u.operand) = arguments;
207     exec->uncheckedR(unmodifiedArgumentsRegister(pc[1].u.operand)) = arguments;
208     END();
209 }
210
211 SLOW_PATH_DECL(slow_path_create_this)
212 {
213     BEGIN();
214     JSFunction* constructor = jsCast<JSFunction*>(OP(2).jsValue().asCell());
215     
216 #if !ASSERT_DISABLED
217     ConstructData constructData;
218     ASSERT(constructor->methodTable()->getConstructData(constructor, constructData) == ConstructTypeJS);
219 #endif
220
221     size_t inlineCapacity = pc[3].u.operand;
222     Structure* structure = constructor->allocationProfile(exec, inlineCapacity)->structure();
223     RETURN(constructEmptyObject(exec, structure));
224 }
225
226 SLOW_PATH_DECL(slow_path_to_this)
227 {
228     BEGIN();
229     JSValue v1 = OP(1).jsValue();
230 #if ENABLE(VALUE_PROFILER)
231     pc[OPCODE_LENGTH(op_to_this) - 1].u.profile->m_buckets[0] =
232         JSValue::encode(v1.structureOrUndefined());
233 #endif
234     RETURN(v1.toThis(exec, exec->codeBlock()->isStrictMode() ? StrictMode : NotStrictMode));
235 }
236
237 SLOW_PATH_DECL(slow_path_not)
238 {
239     BEGIN();
240     RETURN(jsBoolean(!OP_C(2).jsValue().toBoolean(exec)));
241 }
242
243 SLOW_PATH_DECL(slow_path_eq)
244 {
245     BEGIN();
246     RETURN(jsBoolean(JSValue::equal(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
247 }
248
249 SLOW_PATH_DECL(slow_path_neq)
250 {
251     BEGIN();
252     RETURN(jsBoolean(!JSValue::equal(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
253 }
254
255 SLOW_PATH_DECL(slow_path_stricteq)
256 {
257     BEGIN();
258     RETURN(jsBoolean(JSValue::strictEqual(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
259 }
260
261 SLOW_PATH_DECL(slow_path_nstricteq)
262 {
263     BEGIN();
264     RETURN(jsBoolean(!JSValue::strictEqual(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
265 }
266
267 SLOW_PATH_DECL(slow_path_less)
268 {
269     BEGIN();
270     RETURN(jsBoolean(jsLess<true>(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
271 }
272
273 SLOW_PATH_DECL(slow_path_lesseq)
274 {
275     BEGIN();
276     RETURN(jsBoolean(jsLessEq<true>(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
277 }
278
279 SLOW_PATH_DECL(slow_path_greater)
280 {
281     BEGIN();
282     RETURN(jsBoolean(jsLess<false>(exec, OP_C(3).jsValue(), OP_C(2).jsValue())));
283 }
284
285 SLOW_PATH_DECL(slow_path_greatereq)
286 {
287     BEGIN();
288     RETURN(jsBoolean(jsLessEq<false>(exec, OP_C(3).jsValue(), OP_C(2).jsValue())));
289 }
290
291 SLOW_PATH_DECL(slow_path_inc)
292 {
293     BEGIN();
294     RETURN(jsNumber(OP(1).jsValue().toNumber(exec) + 1));
295 }
296
297 SLOW_PATH_DECL(slow_path_dec)
298 {
299     BEGIN();
300     RETURN(jsNumber(OP(1).jsValue().toNumber(exec) - 1));
301 }
302
303 SLOW_PATH_DECL(slow_path_to_number)
304 {
305     BEGIN();
306     RETURN(jsNumber(OP_C(2).jsValue().toNumber(exec)));
307 }
308
309 SLOW_PATH_DECL(slow_path_negate)
310 {
311     BEGIN();
312     RETURN(jsNumber(-OP_C(2).jsValue().toNumber(exec)));
313 }
314
315 SLOW_PATH_DECL(slow_path_add)
316 {
317     BEGIN();
318     JSValue v1 = OP_C(2).jsValue();
319     JSValue v2 = OP_C(3).jsValue();
320     
321     if (v1.isString() && !v2.isObject())
322         RETURN(jsString(exec, asString(v1), v2.toString(exec)));
323     
324     if (v1.isNumber() && v2.isNumber())
325         RETURN(jsNumber(v1.asNumber() + v2.asNumber()));
326     
327     RETURN(jsAddSlowCase(exec, v1, v2));
328 }
329
330 // The following arithmetic and bitwise operations need to be sure to run
331 // toNumber() on their operands in order.  (A call to toNumber() is idempotent
332 // if an exception is already set on the ExecState.)
333
334 SLOW_PATH_DECL(slow_path_mul)
335 {
336     BEGIN();
337     double a = OP_C(2).jsValue().toNumber(exec);
338     double b = OP_C(3).jsValue().toNumber(exec);
339     RETURN(jsNumber(a * b));
340 }
341
342 SLOW_PATH_DECL(slow_path_sub)
343 {
344     BEGIN();
345     double a = OP_C(2).jsValue().toNumber(exec);
346     double b = OP_C(3).jsValue().toNumber(exec);
347     RETURN(jsNumber(a - b));
348 }
349
350 SLOW_PATH_DECL(slow_path_div)
351 {
352     BEGIN();
353     double a = OP_C(2).jsValue().toNumber(exec);
354     double b = OP_C(3).jsValue().toNumber(exec);
355     RETURN(jsNumber(a / b));
356 }
357
358 SLOW_PATH_DECL(slow_path_mod)
359 {
360     BEGIN();
361     double a = OP_C(2).jsValue().toNumber(exec);
362     double b = OP_C(3).jsValue().toNumber(exec);
363     RETURN(jsNumber(fmod(a, b)));
364 }
365
366 SLOW_PATH_DECL(slow_path_lshift)
367 {
368     BEGIN();
369     int32_t a = OP_C(2).jsValue().toInt32(exec);
370     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
371     RETURN(jsNumber(a << (b & 31)));
372 }
373
374 SLOW_PATH_DECL(slow_path_rshift)
375 {
376     BEGIN();
377     int32_t a = OP_C(2).jsValue().toInt32(exec);
378     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
379     RETURN(jsNumber(a >> (b & 31)));
380 }
381
382 SLOW_PATH_DECL(slow_path_urshift)
383 {
384     BEGIN();
385     uint32_t a = OP_C(2).jsValue().toUInt32(exec);
386     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
387     RETURN(jsNumber(a >> (b & 31)));
388 }
389
390 SLOW_PATH_DECL(slow_path_bitand)
391 {
392     BEGIN();
393     int32_t a = OP_C(2).jsValue().toInt32(exec);
394     int32_t b = OP_C(3).jsValue().toInt32(exec);
395     RETURN(jsNumber(a & b));
396 }
397
398 SLOW_PATH_DECL(slow_path_bitor)
399 {
400     BEGIN();
401     int32_t a = OP_C(2).jsValue().toInt32(exec);
402     int32_t b = OP_C(3).jsValue().toInt32(exec);
403     RETURN(jsNumber(a | b));
404 }
405
406 SLOW_PATH_DECL(slow_path_bitxor)
407 {
408     BEGIN();
409     int32_t a = OP_C(2).jsValue().toInt32(exec);
410     int32_t b = OP_C(3).jsValue().toInt32(exec);
411     RETURN(jsNumber(a ^ b));
412 }
413
414 SLOW_PATH_DECL(slow_path_typeof)
415 {
416     BEGIN();
417     RETURN(jsTypeStringForValue(exec, OP_C(2).jsValue()));
418 }
419
420 SLOW_PATH_DECL(slow_path_is_object)
421 {
422     BEGIN();
423     RETURN(jsBoolean(jsIsObjectType(exec, OP_C(2).jsValue())));
424 }
425
426 SLOW_PATH_DECL(slow_path_is_function)
427 {
428     BEGIN();
429     RETURN(jsBoolean(jsIsFunctionType(OP_C(2).jsValue())));
430 }
431
432 SLOW_PATH_DECL(slow_path_in)
433 {
434     BEGIN();
435     RETURN(jsBoolean(CommonSlowPaths::opIn(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
436 }
437
438 SLOW_PATH_DECL(slow_path_del_by_val)
439 {
440     BEGIN();
441     JSValue baseValue = OP_C(2).jsValue();
442     JSObject* baseObject = baseValue.toObject(exec);
443     
444     JSValue subscript = OP_C(3).jsValue();
445     
446     bool couldDelete;
447     
448     uint32_t i;
449     if (subscript.getUInt32(i))
450         couldDelete = baseObject->methodTable()->deletePropertyByIndex(baseObject, exec, i);
451     else if (isName(subscript))
452         couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, jsCast<NameInstance*>(subscript.asCell())->privateName());
453     else {
454         CHECK_EXCEPTION();
455         Identifier property(exec, subscript.toString(exec)->value(exec));
456         CHECK_EXCEPTION();
457         couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, property);
458     }
459     
460     if (!couldDelete && exec->codeBlock()->isStrictMode())
461         THROW(createTypeError(exec, "Unable to delete property."));
462     
463     RETURN(jsBoolean(couldDelete));
464 }
465
466 SLOW_PATH_DECL(slow_path_strcat)
467 {
468     BEGIN();
469     RETURN(jsString(exec, &OP(2), pc[3].u.operand));
470 }
471
472 SLOW_PATH_DECL(slow_path_to_primitive)
473 {
474     BEGIN();
475     RETURN(OP_C(2).jsValue().toPrimitive(exec));
476 }
477
478 } // namespace JSC
479
480 #endif // ENABLE(JIT) || ENABLE(LLINT)