Remove excessive headers from JavaScriptCore
[WebKit-https.git] / Source / JavaScriptCore / runtime / CommonSlowPaths.cpp
1 /*
2  * Copyright (C) 2011-2017 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 #include "ArithProfile.h"
30 #include "ArrayConstructor.h"
31 #include "BuiltinNames.h"
32 #include "CallFrame.h"
33 #include "ClonedArguments.h"
34 #include "CodeProfiling.h"
35 #include "CommonSlowPathsExceptions.h"
36 #include "DefinePropertyAttributes.h"
37 #include "DirectArguments.h"
38 #include "Error.h"
39 #include "ErrorHandlingScope.h"
40 #include "ExceptionFuzz.h"
41 #include "FrameTracers.h"
42 #include "GetterSetter.h"
43 #include "HostCallReturnValue.h"
44 #include "ICStats.h"
45 #include "Interpreter.h"
46 #include "IteratorOperations.h"
47 #include "JIT.h"
48 #include "JSArrayInlines.h"
49 #include "JSCInlines.h"
50 #include "JSCJSValue.h"
51 #include "JSFixedArray.h"
52 #include "JSGlobalObjectFunctions.h"
53 #include "JSLexicalEnvironment.h"
54 #include "JSPropertyNameEnumerator.h"
55 #include "JSString.h"
56 #include "JSWithScope.h"
57 #include "LLIntCommon.h"
58 #include "LLIntExceptions.h"
59 #include "LowLevelInterpreter.h"
60 #include "MathCommon.h"
61 #include "ObjectConstructor.h"
62 #include "ScopedArguments.h"
63 #include "StructureRareDataInlines.h"
64 #include "ThunkGenerators.h"
65 #include "TypeProfilerLog.h"
66 #include <wtf/StringPrintStream.h>
67
68 namespace JSC {
69
70 #define BEGIN_NO_SET_PC() \
71     VM& vm = exec->vm();      \
72     NativeCallFrameTracer tracer(&vm, exec); \
73     auto throwScope = DECLARE_THROW_SCOPE(vm); \
74     UNUSED_PARAM(throwScope)
75
76 #ifndef NDEBUG
77 #define SET_PC_FOR_STUBS() do { \
78         exec->codeBlock()->bytecodeOffset(pc); \
79         exec->setCurrentVPC(pc + 1); \
80     } while (false)
81 #else
82 #define SET_PC_FOR_STUBS() do { \
83         exec->setCurrentVPC(pc + 1); \
84     } while (false)
85 #endif
86
87 #define RETURN_TO_THROW(exec, pc)   pc = LLInt::returnToThrow(exec)
88
89 #define BEGIN()                           \
90     BEGIN_NO_SET_PC();                    \
91     SET_PC_FOR_STUBS()
92
93 #define OP(index) (exec->uncheckedR(pc[index].u.operand))
94 #define OP_C(index) (exec->r(pc[index].u.operand))
95
96 #define RETURN_TWO(first, second) do {       \
97         return encodeResult(first, second);        \
98     } while (false)
99
100 #define END_IMPL() RETURN_TWO(pc, exec)
101
102 #define THROW(exceptionToThrow) do {                        \
103         throwException(exec, throwScope, exceptionToThrow); \
104         RETURN_TO_THROW(exec, pc);                          \
105         END_IMPL();                                         \
106     } while (false)
107
108 #define CHECK_EXCEPTION() do {                    \
109         doExceptionFuzzingIfEnabled(exec, throwScope, "CommonSlowPaths", pc);   \
110         if (UNLIKELY(throwScope.exception())) {   \
111             RETURN_TO_THROW(exec, pc);            \
112             END_IMPL();                           \
113         }                                         \
114     } while (false)
115
116 #define END() do {                        \
117         CHECK_EXCEPTION();                \
118         END_IMPL();                       \
119     } while (false)
120
121 #define BRANCH(opcode, condition) do {                      \
122         bool bCondition = (condition);                         \
123         CHECK_EXCEPTION();                                  \
124         if (bCondition)                                        \
125             pc += pc[OPCODE_LENGTH(opcode) - 1].u.operand;        \
126         else                                                      \
127             pc += OPCODE_LENGTH(opcode);                          \
128         END_IMPL();                                         \
129     } while (false)
130
131 #define RETURN_WITH_PROFILING(value__, profilingAction__) do { \
132         JSValue returnValue__ = (value__);  \
133         CHECK_EXCEPTION();                  \
134         OP(1) = returnValue__;              \
135         profilingAction__;                  \
136         END_IMPL();                         \
137     } while (false)
138
139 #define RETURN(value) \
140     RETURN_WITH_PROFILING(value, { })
141
142 #define RETURN_PROFILED(opcode__, value__) \
143     RETURN_WITH_PROFILING(value__, PROFILE_VALUE(opcode__, returnValue__))
144
145 #define PROFILE_VALUE(opcode, value) do { \
146         pc[OPCODE_LENGTH(opcode) - 1].u.profile->m_buckets[0] = \
147         JSValue::encode(value);                  \
148     } while (false)
149
150 #define CALL_END_IMPL(exec, callTarget) RETURN_TWO((callTarget), (exec))
151
152 #define CALL_CHECK_EXCEPTION(exec, pc) do {                          \
153         ExecState* cceExec = (exec);                                 \
154         Instruction* ccePC = (pc);                                   \
155         if (UNLIKELY(throwScope.exception()))                        \
156             CALL_END_IMPL(cceExec, LLInt::callToThrow(cceExec));     \
157     } while (false)
158
159 #define CALL_RETURN(exec, pc, callTarget) do {                    \
160         ExecState* crExec = (exec);                                  \
161         Instruction* crPC = (pc);                                    \
162         void* crCallTarget = (callTarget);                           \
163         CALL_CHECK_EXCEPTION(crExec->callerFrame(), crPC);  \
164         CALL_END_IMPL(crExec, crCallTarget);                \
165     } while (false)
166
167 static CommonSlowPaths::ArityCheckData* setupArityCheckData(VM& vm, int slotsToAdd)
168 {
169     CommonSlowPaths::ArityCheckData* result = vm.arityCheckData.get();
170     result->paddedStackSpace = slotsToAdd;
171 #if ENABLE(JIT)
172     if (vm.canUseJIT())
173         result->thunkToCall = vm.getCTIStub(arityFixupGenerator).code().executableAddress();
174     else
175 #endif
176         result->thunkToCall = 0;
177     return result;
178 }
179
180 SLOW_PATH_DECL(slow_path_call_arityCheck)
181 {
182     BEGIN();
183     int slotsToAdd = CommonSlowPaths::arityCheckFor(exec, vm, CodeForCall);
184     if (slotsToAdd < 0) {
185         exec = exec->callerFrame();
186         vm.topCallFrame = exec;
187         ErrorHandlingScope errorScope(vm);
188         throwScope.release();
189         CommonSlowPaths::interpreterThrowInCaller(exec, createStackOverflowError(exec));
190         RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
191     }
192     RETURN_TWO(0, setupArityCheckData(vm, slotsToAdd));
193 }
194
195 SLOW_PATH_DECL(slow_path_construct_arityCheck)
196 {
197     BEGIN();
198     int slotsToAdd = CommonSlowPaths::arityCheckFor(exec, vm, CodeForConstruct);
199     if (slotsToAdd < 0) {
200         exec = exec->callerFrame();
201         vm.topCallFrame = exec;
202         ErrorHandlingScope errorScope(vm);
203         CommonSlowPaths::interpreterThrowInCaller(exec, createStackOverflowError(exec));
204         RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
205     }
206     RETURN_TWO(0, setupArityCheckData(vm, slotsToAdd));
207 }
208
209 SLOW_PATH_DECL(slow_path_create_direct_arguments)
210 {
211     BEGIN();
212     RETURN(DirectArguments::createByCopying(exec));
213 }
214
215 SLOW_PATH_DECL(slow_path_create_scoped_arguments)
216 {
217     BEGIN();
218     JSLexicalEnvironment* scope = jsCast<JSLexicalEnvironment*>(OP(2).jsValue());
219     ScopedArgumentsTable* table = scope->symbolTable()->arguments();
220     RETURN(ScopedArguments::createByCopying(exec, table, scope));
221 }
222
223 SLOW_PATH_DECL(slow_path_create_cloned_arguments)
224 {
225     BEGIN();
226     RETURN(ClonedArguments::createWithMachineFrame(exec, exec, ArgumentsMode::Cloned));
227 }
228
229 SLOW_PATH_DECL(slow_path_create_this)
230 {
231     BEGIN();
232     JSObject* result;
233     JSObject* constructorAsObject = asObject(OP(2).jsValue());
234     if (constructorAsObject->type() == JSFunctionType) {
235         JSFunction* constructor = jsCast<JSFunction*>(constructorAsObject);
236         auto& cacheWriteBarrier = pc[4].u.jsCell;
237         if (!cacheWriteBarrier)
238             cacheWriteBarrier.set(exec->vm(), exec->codeBlock(), constructor);
239         else if (cacheWriteBarrier.unvalidatedGet() != JSCell::seenMultipleCalleeObjects() && cacheWriteBarrier.get() != constructor)
240             cacheWriteBarrier.setWithoutWriteBarrier(JSCell::seenMultipleCalleeObjects());
241
242         size_t inlineCapacity = pc[3].u.operand;
243         Structure* structure = constructor->rareData(exec, inlineCapacity)->objectAllocationProfile()->structure();
244         result = constructEmptyObject(exec, structure);
245     } else {
246         // http://ecma-international.org/ecma-262/6.0/#sec-ordinarycreatefromconstructor
247         JSValue proto = constructorAsObject->get(exec, exec->propertyNames().prototype);
248         CHECK_EXCEPTION();
249         if (proto.isObject())
250             result = constructEmptyObject(exec, asObject(proto));
251         else
252             result = constructEmptyObject(exec);
253     }
254     RETURN(result);
255 }
256
257 SLOW_PATH_DECL(slow_path_to_this)
258 {
259     BEGIN();
260     JSValue v1 = OP(1).jsValue();
261     if (v1.isCell()) {
262         Structure* myStructure = v1.asCell()->structure(vm);
263         Structure* otherStructure = pc[2].u.structure.get();
264         if (myStructure != otherStructure) {
265             if (otherStructure)
266                 pc[3].u.toThisStatus = ToThisConflicted;
267             pc[2].u.structure.set(vm, exec->codeBlock(), myStructure);
268         }
269     } else {
270         pc[3].u.toThisStatus = ToThisConflicted;
271         pc[2].u.structure.clear();
272     }
273     RETURN(v1.toThis(exec, exec->codeBlock()->isStrictMode() ? StrictMode : NotStrictMode));
274 }
275
276 SLOW_PATH_DECL(slow_path_throw_tdz_error)
277 {
278     BEGIN();
279     THROW(createTDZError(exec));
280 }
281
282 SLOW_PATH_DECL(slow_path_throw_strict_mode_readonly_property_write_error)
283 {
284     BEGIN();
285     THROW(createTypeError(exec, ASCIILiteral(ReadonlyPropertyWriteError)));
286 }
287
288 SLOW_PATH_DECL(slow_path_not)
289 {
290     BEGIN();
291     RETURN(jsBoolean(!OP_C(2).jsValue().toBoolean(exec)));
292 }
293
294 SLOW_PATH_DECL(slow_path_eq)
295 {
296     BEGIN();
297     RETURN(jsBoolean(JSValue::equal(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
298 }
299
300 SLOW_PATH_DECL(slow_path_neq)
301 {
302     BEGIN();
303     RETURN(jsBoolean(!JSValue::equal(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
304 }
305
306 SLOW_PATH_DECL(slow_path_stricteq)
307 {
308     BEGIN();
309     RETURN(jsBoolean(JSValue::strictEqual(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
310 }
311
312 SLOW_PATH_DECL(slow_path_nstricteq)
313 {
314     BEGIN();
315     RETURN(jsBoolean(!JSValue::strictEqual(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
316 }
317
318 SLOW_PATH_DECL(slow_path_less)
319 {
320     BEGIN();
321     RETURN(jsBoolean(jsLess<true>(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
322 }
323
324 SLOW_PATH_DECL(slow_path_lesseq)
325 {
326     BEGIN();
327     RETURN(jsBoolean(jsLessEq<true>(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
328 }
329
330 SLOW_PATH_DECL(slow_path_greater)
331 {
332     BEGIN();
333     RETURN(jsBoolean(jsLess<false>(exec, OP_C(3).jsValue(), OP_C(2).jsValue())));
334 }
335
336 SLOW_PATH_DECL(slow_path_greatereq)
337 {
338     BEGIN();
339     RETURN(jsBoolean(jsLessEq<false>(exec, OP_C(3).jsValue(), OP_C(2).jsValue())));
340 }
341
342 SLOW_PATH_DECL(slow_path_inc)
343 {
344     BEGIN();
345     RETURN(jsNumber(OP(1).jsValue().toNumber(exec) + 1));
346 }
347
348 SLOW_PATH_DECL(slow_path_dec)
349 {
350     BEGIN();
351     RETURN(jsNumber(OP(1).jsValue().toNumber(exec) - 1));
352 }
353
354 SLOW_PATH_DECL(slow_path_to_string)
355 {
356     BEGIN();
357     RETURN(OP_C(2).jsValue().toString(exec));
358 }
359
360 #if ENABLE(JIT)
361 static void updateArithProfileForUnaryArithOp(Instruction* pc, JSValue result, JSValue operand)
362 {
363     ArithProfile& profile = *bitwise_cast<ArithProfile*>(&pc[3].u.operand);
364     profile.observeLHS(operand);
365     ASSERT(result.isNumber());
366     if (!result.isInt32()) {
367         if (operand.isInt32())
368             profile.setObservedInt32Overflow();
369
370         double doubleVal = result.asNumber();
371         if (!doubleVal && std::signbit(doubleVal))
372             profile.setObservedNegZeroDouble();
373         else {
374             profile.setObservedNonNegZeroDouble();
375
376             // The Int52 overflow check here intentionally omits 1ll << 51 as a valid negative Int52 value.
377             // Therefore, we will get a false positive if the result is that value. This is intentionally
378             // done to simplify the checking algorithm.
379             static const int64_t int52OverflowPoint = (1ll << 51);
380             int64_t int64Val = static_cast<int64_t>(std::abs(doubleVal));
381             if (int64Val >= int52OverflowPoint)
382                 profile.setObservedInt52Overflow();
383         }
384     }
385 }
386 #else
387 static void updateArithProfileForUnaryArithOp(Instruction*, JSValue, JSValue) { }
388 #endif
389
390 SLOW_PATH_DECL(slow_path_negate)
391 {
392     BEGIN();
393     JSValue operand = OP_C(2).jsValue();
394     JSValue result = jsNumber(-operand.toNumber(exec));
395     RETURN_WITH_PROFILING(result, {
396         updateArithProfileForUnaryArithOp(pc, result, operand);
397     });
398 }
399
400 #if ENABLE(DFG_JIT)
401 static void updateArithProfileForBinaryArithOp(ExecState* exec, Instruction* pc, JSValue result, JSValue left, JSValue right)
402 {
403     CodeBlock* codeBlock = exec->codeBlock();
404     ArithProfile& profile = *codeBlock->arithProfileForPC(pc);
405
406     if (result.isNumber()) {
407         if (!result.isInt32()) {
408             if (left.isInt32() && right.isInt32())
409                 profile.setObservedInt32Overflow();
410
411             double doubleVal = result.asNumber();
412             if (!doubleVal && std::signbit(doubleVal))
413                 profile.setObservedNegZeroDouble();
414             else {
415                 profile.setObservedNonNegZeroDouble();
416
417                 // The Int52 overflow check here intentionally omits 1ll << 51 as a valid negative Int52 value.
418                 // Therefore, we will get a false positive if the result is that value. This is intentionally
419                 // done to simplify the checking algorithm.
420                 static const int64_t int52OverflowPoint = (1ll << 51);
421                 int64_t int64Val = static_cast<int64_t>(std::abs(doubleVal));
422                 if (int64Val >= int52OverflowPoint)
423                     profile.setObservedInt52Overflow();
424             }
425         }
426     } else
427         profile.setObservedNonNumber();
428 }
429 #else
430 static void updateArithProfileForBinaryArithOp(ExecState*, Instruction*, JSValue, JSValue, JSValue) { }
431 #endif
432
433 SLOW_PATH_DECL(slow_path_to_number)
434 {
435     BEGIN();
436     JSValue argument = OP_C(2).jsValue();
437     JSValue result = jsNumber(argument.toNumber(exec));
438     RETURN_PROFILED(op_to_number, result);
439 }
440
441 SLOW_PATH_DECL(slow_path_add)
442 {
443     BEGIN();
444     JSValue v1 = OP_C(2).jsValue();
445     JSValue v2 = OP_C(3).jsValue();
446     JSValue result;
447
448     ArithProfile& arithProfile = *exec->codeBlock()->arithProfileForPC(pc);
449     arithProfile.observeLHSAndRHS(v1, v2);
450
451     if (v1.isString() && !v2.isObject()) {
452         JSString* v2String = v2.toString(exec);
453         if (LIKELY(!throwScope.exception()))
454             result = jsString(exec, asString(v1), v2String);
455     } else if (v1.isNumber() && v2.isNumber())
456         result = jsNumber(v1.asNumber() + v2.asNumber());
457     else
458         result = jsAddSlowCase(exec, v1, v2);
459
460     RETURN_WITH_PROFILING(result, {
461         updateArithProfileForBinaryArithOp(exec, pc, result, v1, v2);
462     });
463 }
464
465 // The following arithmetic and bitwise operations need to be sure to run
466 // toNumber() on their operands in order.  (A call to toNumber() is idempotent
467 // if an exception is already set on the ExecState.)
468
469 SLOW_PATH_DECL(slow_path_mul)
470 {
471     BEGIN();
472     JSValue left = OP_C(2).jsValue();
473     JSValue right = OP_C(3).jsValue();
474     double a = left.toNumber(exec);
475     if (UNLIKELY(throwScope.exception()))
476         RETURN(JSValue());
477     double b = right.toNumber(exec);
478     JSValue result = jsNumber(a * b);
479     RETURN_WITH_PROFILING(result, {
480         updateArithProfileForBinaryArithOp(exec, pc, result, left, right);
481     });
482 }
483
484 SLOW_PATH_DECL(slow_path_sub)
485 {
486     BEGIN();
487     JSValue left = OP_C(2).jsValue();
488     JSValue right = OP_C(3).jsValue();
489     double a = left.toNumber(exec);
490     if (UNLIKELY(throwScope.exception()))
491         RETURN(JSValue());
492     double b = right.toNumber(exec);
493     JSValue result = jsNumber(a - b);
494     RETURN_WITH_PROFILING(result, {
495         updateArithProfileForBinaryArithOp(exec, pc, result, left, right);
496     });
497 }
498
499 SLOW_PATH_DECL(slow_path_div)
500 {
501     BEGIN();
502     JSValue left = OP_C(2).jsValue();
503     JSValue right = OP_C(3).jsValue();
504     double a = left.toNumber(exec);
505     if (UNLIKELY(throwScope.exception()))
506         RETURN(JSValue());
507     double b = right.toNumber(exec);
508     if (UNLIKELY(throwScope.exception()))
509         RETURN(JSValue());
510     JSValue result = jsNumber(a / b);
511     RETURN_WITH_PROFILING(result, {
512         updateArithProfileForBinaryArithOp(exec, pc, result, left, right);
513     });
514 }
515
516 SLOW_PATH_DECL(slow_path_mod)
517 {
518     BEGIN();
519     double a = OP_C(2).jsValue().toNumber(exec);
520     if (UNLIKELY(throwScope.exception()))
521         RETURN(JSValue());
522     double b = OP_C(3).jsValue().toNumber(exec);
523     RETURN(jsNumber(jsMod(a, b)));
524 }
525
526 SLOW_PATH_DECL(slow_path_pow)
527 {
528     BEGIN();
529     double a = OP_C(2).jsValue().toNumber(exec);
530     if (UNLIKELY(throwScope.exception()))
531         RETURN(JSValue());
532     double b = OP_C(3).jsValue().toNumber(exec);
533     if (UNLIKELY(throwScope.exception()))
534         RETURN(JSValue());
535     RETURN(jsNumber(operationMathPow(a, b)));
536 }
537
538 SLOW_PATH_DECL(slow_path_lshift)
539 {
540     BEGIN();
541     int32_t a = OP_C(2).jsValue().toInt32(exec);
542     if (UNLIKELY(throwScope.exception()))
543         RETURN(JSValue());
544     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
545     RETURN(jsNumber(a << (b & 31)));
546 }
547
548 SLOW_PATH_DECL(slow_path_rshift)
549 {
550     BEGIN();
551     int32_t a = OP_C(2).jsValue().toInt32(exec);
552     if (UNLIKELY(throwScope.exception()))
553         RETURN(JSValue());
554     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
555     RETURN(jsNumber(a >> (b & 31)));
556 }
557
558 SLOW_PATH_DECL(slow_path_urshift)
559 {
560     BEGIN();
561     uint32_t a = OP_C(2).jsValue().toUInt32(exec);
562     if (UNLIKELY(throwScope.exception()))
563         RETURN(JSValue());
564     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
565     RETURN(jsNumber(static_cast<int32_t>(a >> (b & 31))));
566 }
567
568 SLOW_PATH_DECL(slow_path_unsigned)
569 {
570     BEGIN();
571     uint32_t a = OP_C(2).jsValue().toUInt32(exec);
572     RETURN(jsNumber(a));
573 }
574
575 SLOW_PATH_DECL(slow_path_bitand)
576 {
577     BEGIN();
578     int32_t a = OP_C(2).jsValue().toInt32(exec);
579     if (UNLIKELY(throwScope.exception()))
580         RETURN(JSValue());
581     int32_t b = OP_C(3).jsValue().toInt32(exec);
582     RETURN(jsNumber(a & b));
583 }
584
585 SLOW_PATH_DECL(slow_path_bitor)
586 {
587     BEGIN();
588     int32_t a = OP_C(2).jsValue().toInt32(exec);
589     if (UNLIKELY(throwScope.exception()))
590         RETURN(JSValue());
591     int32_t b = OP_C(3).jsValue().toInt32(exec);
592     RETURN(jsNumber(a | b));
593 }
594
595 SLOW_PATH_DECL(slow_path_bitxor)
596 {
597     BEGIN();
598     int32_t a = OP_C(2).jsValue().toInt32(exec);
599     if (UNLIKELY(throwScope.exception()))
600         RETURN(JSValue());
601     int32_t b = OP_C(3).jsValue().toInt32(exec);
602     RETURN(jsNumber(a ^ b));
603 }
604
605 SLOW_PATH_DECL(slow_path_typeof)
606 {
607     BEGIN();
608     RETURN(jsTypeStringForValue(exec, OP_C(2).jsValue()));
609 }
610
611 SLOW_PATH_DECL(slow_path_is_object_or_null)
612 {
613     BEGIN();
614     RETURN(jsBoolean(jsIsObjectTypeOrNull(exec, OP_C(2).jsValue())));
615 }
616
617 SLOW_PATH_DECL(slow_path_is_function)
618 {
619     BEGIN();
620     RETURN(jsBoolean(jsIsFunctionType(OP_C(2).jsValue())));
621 }
622
623 SLOW_PATH_DECL(slow_path_in)
624 {
625     BEGIN();
626     RETURN(jsBoolean(CommonSlowPaths::opIn(exec, OP_C(2).jsValue(), OP_C(3).jsValue(), pc[4].u.arrayProfile)));
627 }
628
629 SLOW_PATH_DECL(slow_path_del_by_val)
630 {
631     BEGIN();
632     JSValue baseValue = OP_C(2).jsValue();
633     JSObject* baseObject = baseValue.toObject(exec);
634     CHECK_EXCEPTION();
635     
636     JSValue subscript = OP_C(3).jsValue();
637     
638     bool couldDelete;
639     
640     uint32_t i;
641     if (subscript.getUInt32(i))
642         couldDelete = baseObject->methodTable(vm)->deletePropertyByIndex(baseObject, exec, i);
643     else {
644         CHECK_EXCEPTION();
645         auto property = subscript.toPropertyKey(exec);
646         CHECK_EXCEPTION();
647         couldDelete = baseObject->methodTable(vm)->deleteProperty(baseObject, exec, property);
648     }
649     
650     if (!couldDelete && exec->codeBlock()->isStrictMode())
651         THROW(createTypeError(exec, UnableToDeletePropertyError));
652     
653     RETURN(jsBoolean(couldDelete));
654 }
655
656 SLOW_PATH_DECL(slow_path_strcat)
657 {
658     BEGIN();
659     RETURN(jsStringFromRegisterArray(exec, &OP(2), pc[3].u.operand));
660 }
661
662 SLOW_PATH_DECL(slow_path_to_primitive)
663 {
664     BEGIN();
665     RETURN(OP_C(2).jsValue().toPrimitive(exec));
666 }
667
668 SLOW_PATH_DECL(slow_path_enter)
669 {
670     BEGIN();
671     CodeBlock* codeBlock = exec->codeBlock();
672     Heap::heap(codeBlock)->writeBarrier(codeBlock);
673     END();
674 }
675
676 SLOW_PATH_DECL(slow_path_get_enumerable_length)
677 {
678     BEGIN();
679     JSValue enumeratorValue = OP(2).jsValue();
680     if (enumeratorValue.isUndefinedOrNull())
681         RETURN(jsNumber(0));
682
683     JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(enumeratorValue.asCell());
684
685     RETURN(jsNumber(enumerator->indexedLength()));
686 }
687
688 SLOW_PATH_DECL(slow_path_has_indexed_property)
689 {
690     BEGIN();
691     JSObject* base = OP(2).jsValue().toObject(exec);
692     CHECK_EXCEPTION();
693     JSValue property = OP(3).jsValue();
694     pc[4].u.arrayProfile->observeStructure(base->structure(vm));
695     ASSERT(property.isUInt32());
696     RETURN(jsBoolean(base->hasPropertyGeneric(exec, property.asUInt32(), PropertySlot::InternalMethodType::GetOwnProperty)));
697 }
698
699 SLOW_PATH_DECL(slow_path_has_structure_property)
700 {
701     BEGIN();
702     JSObject* base = OP(2).jsValue().toObject(exec);
703     CHECK_EXCEPTION();
704     JSValue property = OP(3).jsValue();
705     ASSERT(property.isString());
706     JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(OP(4).jsValue().asCell());
707     if (base->structure(vm)->id() == enumerator->cachedStructureID())
708         RETURN(jsBoolean(true));
709     JSString* string = asString(property);
710     auto propertyName = string->toIdentifier(exec);
711     CHECK_EXCEPTION();
712     RETURN(jsBoolean(base->hasPropertyGeneric(exec, propertyName, PropertySlot::InternalMethodType::GetOwnProperty)));
713 }
714
715 SLOW_PATH_DECL(slow_path_has_generic_property)
716 {
717     BEGIN();
718     JSObject* base = OP(2).jsValue().toObject(exec);
719     CHECK_EXCEPTION();
720     JSValue property = OP(3).jsValue();
721     JSString* string = asString(property);
722     auto propertyName = string->toIdentifier(exec);
723     CHECK_EXCEPTION();
724     RETURN(jsBoolean(base->hasPropertyGeneric(exec, propertyName, PropertySlot::InternalMethodType::GetOwnProperty)));
725 }
726
727 SLOW_PATH_DECL(slow_path_get_direct_pname)
728 {
729     BEGIN();
730     JSValue baseValue = OP_C(2).jsValue();
731     JSValue property = OP(3).jsValue();
732     JSString* string = asString(property);
733     auto propertyName = string->toIdentifier(exec);
734     CHECK_EXCEPTION();
735     RETURN(baseValue.get(exec, propertyName));
736 }
737
738 SLOW_PATH_DECL(slow_path_get_property_enumerator)
739 {
740     BEGIN();
741     JSValue baseValue = OP(2).jsValue();
742     if (baseValue.isUndefinedOrNull())
743         RETURN(JSPropertyNameEnumerator::create(vm));
744
745     JSObject* base = baseValue.toObject(exec);
746     CHECK_EXCEPTION();
747
748     RETURN(propertyNameEnumerator(exec, base));
749 }
750
751 SLOW_PATH_DECL(slow_path_next_structure_enumerator_pname)
752 {
753     BEGIN();
754     JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(OP(2).jsValue().asCell());
755     uint32_t index = OP(3).jsValue().asUInt32();
756
757     JSString* propertyName = nullptr;
758     if (index < enumerator->endStructurePropertyIndex())
759         propertyName = enumerator->propertyNameAtIndex(index);
760     RETURN(propertyName ? propertyName : jsNull());
761 }
762
763 SLOW_PATH_DECL(slow_path_next_generic_enumerator_pname)
764 {
765     BEGIN();
766     JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(OP(2).jsValue().asCell());
767     uint32_t index = OP(3).jsValue().asUInt32();
768
769     JSString* propertyName = nullptr;
770     if (enumerator->endStructurePropertyIndex() <= index && index < enumerator->endGenericPropertyIndex())
771         propertyName = enumerator->propertyNameAtIndex(index);
772     RETURN(propertyName ? propertyName : jsNull());
773 }
774
775 SLOW_PATH_DECL(slow_path_to_index_string)
776 {
777     BEGIN();
778     RETURN(jsString(exec, Identifier::from(exec, OP(2).jsValue().asUInt32()).string()));
779 }
780
781 SLOW_PATH_DECL(slow_path_profile_type_clear_log)
782 {
783     BEGIN();
784     vm.typeProfilerLog()->processLogEntries(ASCIILiteral("LLInt log full."));
785     END();
786 }
787
788 SLOW_PATH_DECL(slow_path_assert)
789 {
790     BEGIN();
791     RELEASE_ASSERT_WITH_MESSAGE(OP(1).jsValue().asBoolean(), "JS assertion failed at line %d in:\n%s\n", pc[2].u.operand, exec->codeBlock()->sourceCodeForTools().data());
792     END();
793 }
794
795 SLOW_PATH_DECL(slow_path_unreachable)
796 {
797     BEGIN();
798     UNREACHABLE_FOR_PLATFORM();
799     END();
800 }
801
802 SLOW_PATH_DECL(slow_path_create_lexical_environment)
803 {
804     BEGIN();
805     int scopeReg = pc[2].u.operand;
806     JSScope* currentScope = exec->uncheckedR(scopeReg).Register::scope();
807     SymbolTable* symbolTable = jsCast<SymbolTable*>(OP_C(3).jsValue());
808     JSValue initialValue = OP_C(4).jsValue();
809     ASSERT(initialValue == jsUndefined() || initialValue == jsTDZValue());
810     JSScope* newScope = JSLexicalEnvironment::create(vm, exec->lexicalGlobalObject(), currentScope, symbolTable, initialValue);
811     RETURN(newScope);
812 }
813
814 SLOW_PATH_DECL(slow_path_push_with_scope)
815 {
816     BEGIN();
817     JSObject* newScope = OP_C(2).jsValue().toObject(exec);
818     CHECK_EXCEPTION();
819
820     int scopeReg = pc[3].u.operand;
821     JSScope* currentScope = exec->uncheckedR(scopeReg).Register::scope();
822     RETURN(JSWithScope::create(vm, exec->lexicalGlobalObject(), newScope, currentScope));
823 }
824
825 SLOW_PATH_DECL(slow_path_resolve_scope_for_hoisting_func_decl_in_eval)
826 {
827     BEGIN();
828     const Identifier& ident = exec->codeBlock()->identifier(pc[3].u.operand);
829     JSScope* scope = exec->uncheckedR(pc[2].u.operand).Register::scope();
830     JSValue resolvedScope = JSScope::resolveScopeForHoistingFuncDeclInEval(exec, scope, ident);
831
832     CHECK_EXCEPTION();
833
834     RETURN(resolvedScope);
835 }
836
837 SLOW_PATH_DECL(slow_path_resolve_scope)
838 {
839     BEGIN();
840     const Identifier& ident = exec->codeBlock()->identifier(pc[3].u.operand);
841     JSScope* scope = exec->uncheckedR(pc[2].u.operand).Register::scope();
842     JSObject* resolvedScope = JSScope::resolve(exec, scope, ident);
843     // Proxy can throw an error here, e.g. Proxy in with statement's @unscopables.
844     CHECK_EXCEPTION();
845
846     ResolveType resolveType = static_cast<ResolveType>(pc[4].u.operand);
847
848     // ModuleVar does not keep the scope register value alive in DFG.
849     ASSERT(resolveType != ModuleVar);
850
851     if (resolveType == UnresolvedProperty || resolveType == UnresolvedPropertyWithVarInjectionChecks) {
852         if (resolvedScope->isGlobalObject()) {
853             JSGlobalObject* globalObject = jsCast<JSGlobalObject*>(resolvedScope);
854             bool hasProperty = globalObject->hasProperty(exec, ident);
855             CHECK_EXCEPTION();
856             if (hasProperty) {
857                 ConcurrentJSLocker locker(exec->codeBlock()->m_lock);
858                 if (resolveType == UnresolvedProperty)
859                     pc[4].u.operand = GlobalProperty;
860                 else
861                     pc[4].u.operand = GlobalPropertyWithVarInjectionChecks;
862
863                 pc[6].u.pointer = globalObject;
864             }
865         } else if (resolvedScope->isGlobalLexicalEnvironment()) {
866             JSGlobalLexicalEnvironment* globalLexicalEnvironment = jsCast<JSGlobalLexicalEnvironment*>(resolvedScope);
867             ConcurrentJSLocker locker(exec->codeBlock()->m_lock);
868             if (resolveType == UnresolvedProperty)
869                 pc[4].u.operand = GlobalLexicalVar;
870             else
871                 pc[4].u.operand = GlobalLexicalVarWithVarInjectionChecks;
872             pc[6].u.pointer = globalLexicalEnvironment;
873         }
874     }
875
876     RETURN(resolvedScope);
877 }
878
879 SLOW_PATH_DECL(slow_path_create_rest)
880 {
881     BEGIN();
882     unsigned arraySize = OP_C(2).jsValue().asUInt32();
883     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
884     Structure* structure = globalObject->restParameterStructure();
885     unsigned numParamsToSkip = pc[3].u.unsignedValue;
886     JSValue* argumentsToCopyRegion = exec->addressOfArgumentsStart() + numParamsToSkip;
887     RETURN(constructArray(exec, structure, argumentsToCopyRegion, arraySize));
888 }
889
890 SLOW_PATH_DECL(slow_path_get_by_id_with_this)
891 {
892     BEGIN();
893     const Identifier& ident = exec->codeBlock()->identifier(pc[4].u.operand);
894     JSValue baseValue = OP_C(2).jsValue();
895     JSValue thisVal = OP_C(3).jsValue();
896     PropertySlot slot(thisVal, PropertySlot::PropertySlot::InternalMethodType::Get);
897     JSValue result = baseValue.get(exec, ident, slot);
898     RETURN_PROFILED(op_get_by_id_with_this, result);
899 }
900
901 SLOW_PATH_DECL(slow_path_get_by_val_with_this)
902 {
903     BEGIN();
904
905     JSValue baseValue = OP_C(2).jsValue();
906     JSValue thisValue = OP_C(3).jsValue();
907     JSValue subscript = OP_C(4).jsValue();
908
909     if (LIKELY(baseValue.isCell() && subscript.isString())) {
910         VM& vm = exec->vm();
911         Structure& structure = *baseValue.asCell()->structure(vm);
912         if (JSCell::canUseFastGetOwnProperty(structure)) {
913             if (RefPtr<AtomicStringImpl> existingAtomicString = asString(subscript)->toExistingAtomicString(exec)) {
914                 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
915                     RETURN_PROFILED(op_get_by_val_with_this, result);
916             }
917         }
918     }
919     
920     PropertySlot slot(thisValue, PropertySlot::PropertySlot::InternalMethodType::Get);
921     if (subscript.isUInt32()) {
922         uint32_t i = subscript.asUInt32();
923         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
924             RETURN_PROFILED(op_get_by_val_with_this, asString(baseValue)->getIndex(exec, i));
925         
926         RETURN_PROFILED(op_get_by_val_with_this, baseValue.get(exec, i, slot));
927     }
928
929     baseValue.requireObjectCoercible(exec);
930     CHECK_EXCEPTION();
931     auto property = subscript.toPropertyKey(exec);
932     CHECK_EXCEPTION();
933     RETURN_PROFILED(op_get_by_val_with_this, baseValue.get(exec, property, slot));
934 }
935
936 SLOW_PATH_DECL(slow_path_put_by_id_with_this)
937 {
938     BEGIN();
939     CodeBlock* codeBlock = exec->codeBlock();
940     const Identifier& ident = codeBlock->identifier(pc[3].u.operand);
941     JSValue baseValue = OP_C(1).jsValue();
942     JSValue thisVal = OP_C(2).jsValue();
943     JSValue putValue = OP_C(4).jsValue();
944     PutPropertySlot slot(thisVal, codeBlock->isStrictMode(), codeBlock->putByIdContext());
945     baseValue.putInline(exec, ident, putValue, slot);
946     END();
947 }
948
949 SLOW_PATH_DECL(slow_path_put_by_val_with_this)
950 {
951     BEGIN();
952     JSValue baseValue = OP_C(1).jsValue();
953     JSValue thisValue = OP_C(2).jsValue();
954     JSValue subscript = OP_C(3).jsValue();
955     JSValue value = OP_C(4).jsValue();
956     
957     auto property = subscript.toPropertyKey(exec);
958     CHECK_EXCEPTION();
959     PutPropertySlot slot(thisValue, exec->codeBlock()->isStrictMode());
960     baseValue.put(exec, property, value, slot);
961     END();
962 }
963
964 SLOW_PATH_DECL(slow_path_define_data_property)
965 {
966     BEGIN();
967     JSObject* base = asObject(OP_C(1).jsValue());
968     JSValue property = OP_C(2).jsValue();
969     JSValue value = OP_C(3).jsValue();
970     JSValue attributes = OP_C(4).jsValue();
971     ASSERT(attributes.isInt32());
972
973     auto propertyName = property.toPropertyKey(exec);
974     CHECK_EXCEPTION();
975     PropertyDescriptor descriptor = toPropertyDescriptor(value, jsUndefined(), jsUndefined(), DefinePropertyAttributes(attributes.asInt32()));
976     ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor()));
977     base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
978     END();
979 }
980
981 SLOW_PATH_DECL(slow_path_define_accessor_property)
982 {
983     BEGIN();
984     JSObject* base = asObject(OP_C(1).jsValue());
985     JSValue property = OP_C(2).jsValue();
986     JSValue getter = OP_C(3).jsValue();
987     JSValue setter = OP_C(4).jsValue();
988     JSValue attributes = OP_C(5).jsValue();
989     ASSERT(attributes.isInt32());
990
991     auto propertyName = property.toPropertyKey(exec);
992     CHECK_EXCEPTION();
993     PropertyDescriptor descriptor = toPropertyDescriptor(jsUndefined(), getter, setter, DefinePropertyAttributes(attributes.asInt32()));
994     ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor()));
995     base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
996     END();
997 }
998
999 SLOW_PATH_DECL(slow_path_throw_static_error)
1000 {
1001     BEGIN();
1002     JSValue errorMessageValue = OP_C(1).jsValue();
1003     RELEASE_ASSERT(errorMessageValue.isString());
1004     String errorMessage = asString(errorMessageValue)->value(exec);
1005     ErrorType errorType = static_cast<ErrorType>(pc[2].u.unsignedValue);
1006     THROW(createError(exec, errorType, errorMessage));
1007 }
1008
1009 SLOW_PATH_DECL(slow_path_new_array_with_spread)
1010 {
1011     BEGIN();
1012     int numItems = pc[3].u.operand;
1013     ASSERT(numItems >= 0);
1014     const BitVector& bitVector = exec->codeBlock()->unlinkedCodeBlock()->bitVector(pc[4].u.unsignedValue);
1015
1016     JSValue* values = bitwise_cast<JSValue*>(&OP(2));
1017
1018     Checked<unsigned, RecordOverflow> checkedArraySize = 0;
1019     for (int i = 0; i < numItems; i++) {
1020         if (bitVector.get(i)) {
1021             JSValue value = values[-i];
1022             JSFixedArray* array = jsCast<JSFixedArray*>(value);
1023             checkedArraySize += array->size();
1024         } else
1025             checkedArraySize += 1;
1026     }
1027     if (UNLIKELY(checkedArraySize.hasOverflowed()))
1028         THROW(createOutOfMemoryError(exec));
1029
1030     unsigned arraySize = checkedArraySize.unsafeGet();
1031     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1032     Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
1033
1034     JSArray* result = JSArray::tryCreate(vm, structure, arraySize);
1035     if (UNLIKELY(!result))
1036         THROW(createOutOfMemoryError(exec));
1037     CHECK_EXCEPTION();
1038
1039     unsigned index = 0;
1040     for (int i = 0; i < numItems; i++) {
1041         JSValue value = values[-i];
1042         if (bitVector.get(i)) {
1043             // We are spreading.
1044             JSFixedArray* array = jsCast<JSFixedArray*>(value);
1045             for (unsigned i = 0; i < array->size(); i++) {
1046                 RELEASE_ASSERT(array->get(i));
1047                 result->putDirectIndex(exec, index, array->get(i));
1048                 ++index;
1049             }
1050         } else {
1051             // We are not spreading.
1052             result->putDirectIndex(exec, index, value);
1053             ++index;
1054         }
1055     }
1056
1057     RETURN(result);
1058 }
1059
1060 SLOW_PATH_DECL(slow_path_spread)
1061 {
1062     BEGIN();
1063
1064     JSValue iterable = OP_C(2).jsValue();
1065
1066     if (iterable.isCell() && isJSArray(iterable.asCell())) {
1067         JSArray* array = jsCast<JSArray*>(iterable);
1068         if (array->isIteratorProtocolFastAndNonObservable()) {
1069             // JSFixedArray::createFromArray does not consult the prototype chain,
1070             // so we must be sure that not consulting the prototype chain would
1071             // produce the same value during iteration.
1072             RETURN(JSFixedArray::createFromArray(exec, vm, array));
1073         }
1074     }
1075
1076     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1077
1078     JSArray* array;
1079     {
1080         JSFunction* iterationFunction = globalObject->iteratorProtocolFunction();
1081         CallData callData;
1082         CallType callType = JSC::getCallData(iterationFunction, callData);
1083         ASSERT(callType != CallType::None);
1084
1085         MarkedArgumentBuffer arguments;
1086         arguments.append(iterable);
1087         JSValue arrayResult = call(exec, iterationFunction, callType, callData, jsNull(), arguments);
1088         CHECK_EXCEPTION();
1089         array = jsCast<JSArray*>(arrayResult);
1090     }
1091
1092     RETURN(JSFixedArray::createFromArray(exec, vm, array));
1093 }
1094
1095 } // namespace JSC