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