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