a1578917efb61d4510b2510acf82554765668eaf
[WebKit.git] / Source / JavaScriptCore / runtime / CommonSlowPaths.cpp
1 /*
2  * Copyright (C) 2011-2016 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 "ArrayConstructor.h"
30 #include "BuiltinNames.h"
31 #include "CallFrame.h"
32 #include "ClonedArguments.h"
33 #include "CodeProfiling.h"
34 #include "CommonSlowPathsExceptions.h"
35 #include "DirectArguments.h"
36 #include "Error.h"
37 #include "ErrorHandlingScope.h"
38 #include "ExceptionFuzz.h"
39 #include "GeneratorFrame.h"
40 #include "GetterSetter.h"
41 #include "HostCallReturnValue.h"
42 #include "Interpreter.h"
43 #include "JIT.h"
44 #include "JSCInlines.h"
45 #include "JSCJSValue.h"
46 #include "JSGlobalObjectFunctions.h"
47 #include "JSLexicalEnvironment.h"
48 #include "JSPropertyNameEnumerator.h"
49 #include "JSString.h"
50 #include "JSWithScope.h"
51 #include "LLIntCommon.h"
52 #include "LLIntExceptions.h"
53 #include "LowLevelInterpreter.h"
54 #include "MathCommon.h"
55 #include "ObjectConstructor.h"
56 #include "ScopedArguments.h"
57 #include "StructureRareDataInlines.h"
58 #include "TypeProfilerLog.h"
59 #include <wtf/StringPrintStream.h>
60
61 namespace JSC {
62
63 #define BEGIN_NO_SET_PC() \
64     VM& vm = exec->vm();      \
65     NativeCallFrameTracer tracer(&vm, exec)
66
67 #ifndef NDEBUG
68 #define SET_PC_FOR_STUBS() do { \
69         exec->codeBlock()->bytecodeOffset(pc); \
70         exec->setCurrentVPC(pc + 1); \
71     } while (false)
72 #else
73 #define SET_PC_FOR_STUBS() do { \
74         exec->setCurrentVPC(pc + 1); \
75     } while (false)
76 #endif
77
78 #define RETURN_TO_THROW(exec, pc)   pc = LLInt::returnToThrow(exec)
79
80 #define BEGIN()                           \
81     BEGIN_NO_SET_PC();                    \
82     SET_PC_FOR_STUBS()
83
84 #define OP(index) (exec->uncheckedR(pc[index].u.operand))
85 #define OP_C(index) (exec->r(pc[index].u.operand))
86
87 #define RETURN_TWO(first, second) do {       \
88         return encodeResult(first, second);        \
89     } while (false)
90
91 #define END_IMPL() RETURN_TWO(pc, exec)
92
93 #define THROW(exceptionToThrow) do {                        \
94         vm.throwException(exec, exceptionToThrow);          \
95         RETURN_TO_THROW(exec, pc);                          \
96         END_IMPL();                                         \
97     } while (false)
98
99 #define CHECK_EXCEPTION() do {                    \
100         doExceptionFuzzingIfEnabled(exec, "CommonSlowPaths", pc);   \
101         if (UNLIKELY(vm.exception())) {           \
102             RETURN_TO_THROW(exec, pc);               \
103             END_IMPL();                           \
104         }                                               \
105     } while (false)
106
107 #define END() do {                        \
108         CHECK_EXCEPTION();                \
109         END_IMPL();                       \
110     } while (false)
111
112 #define BRANCH(opcode, condition) do {                      \
113         bool bCondition = (condition);                         \
114         CHECK_EXCEPTION();                                  \
115         if (bCondition)                                        \
116             pc += pc[OPCODE_LENGTH(opcode) - 1].u.operand;        \
117         else                                                      \
118             pc += OPCODE_LENGTH(opcode);                          \
119         END_IMPL();                                         \
120     } while (false)
121
122 #define RETURN_WITH_PROFILING(value__, profilingAction__) do { \
123         JSValue returnValue__ = (value__);  \
124         CHECK_EXCEPTION();                  \
125         OP(1) = returnValue__;              \
126         profilingAction__;                  \
127         END_IMPL();                         \
128     } while (false)
129
130 #define RETURN(value) \
131     RETURN_WITH_PROFILING(value, { })
132
133 #define RETURN_PROFILED(opcode__, value__) \
134     RETURN_WITH_PROFILING(value__, PROFILE_VALUE(opcode__, returnValue__))
135
136 #define PROFILE_VALUE(opcode, value) do { \
137         pc[OPCODE_LENGTH(opcode) - 1].u.profile->m_buckets[0] = \
138         JSValue::encode(value);                  \
139     } while (false)
140
141 #define CALL_END_IMPL(exec, callTarget) RETURN_TWO((callTarget), (exec))
142
143 #define CALL_THROW(exec, pc, exceptionToThrow) do {                     \
144         ExecState* ctExec = (exec);                                     \
145         Instruction* ctPC = (pc);                                       \
146         vm.throwException(exec, exceptionToThrow);                      \
147         CALL_END_IMPL(ctExec, LLInt::callToThrow(ctExec));              \
148     } while (false)
149
150 #define CALL_CHECK_EXCEPTION(exec, pc) do {                          \
151         ExecState* cceExec = (exec);                                 \
152         Instruction* ccePC = (pc);                                   \
153         if (UNLIKELY(vm.exception()))                                \
154             CALL_END_IMPL(cceExec, LLInt::callToThrow(cceExec));     \
155     } while (false)
156
157 #define CALL_RETURN(exec, pc, callTarget) do {                    \
158         ExecState* crExec = (exec);                                  \
159         Instruction* crPC = (pc);                                    \
160         void* crCallTarget = (callTarget);                           \
161         CALL_CHECK_EXCEPTION(crExec->callerFrame(), crPC);  \
162         CALL_END_IMPL(crExec, crCallTarget);                \
163     } while (false)
164
165 static CommonSlowPaths::ArityCheckData* setupArityCheckData(VM& vm, int slotsToAdd)
166 {
167     CommonSlowPaths::ArityCheckData* result = vm.arityCheckData.get();
168     result->paddedStackSpace = slotsToAdd;
169 #if ENABLE(JIT)
170     if (vm.canUseJIT())
171         result->thunkToCall = vm.getCTIStub(arityFixupGenerator).code().executableAddress();
172     else
173 #endif
174         result->thunkToCall = 0;
175     return result;
176 }
177
178 SLOW_PATH_DECL(slow_path_call_arityCheck)
179 {
180     BEGIN();
181     int slotsToAdd = CommonSlowPaths::arityCheckFor(exec, &vm.interpreter->stack(), CodeForCall);
182     if (slotsToAdd < 0) {
183         exec = exec->callerFrame();
184         ErrorHandlingScope errorScope(exec->vm());
185         CommonSlowPaths::interpreterThrowInCaller(exec, createStackOverflowError(exec));
186         RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
187     }
188     RETURN_TWO(0, setupArityCheckData(vm, slotsToAdd));
189 }
190
191 SLOW_PATH_DECL(slow_path_construct_arityCheck)
192 {
193     BEGIN();
194     int slotsToAdd = CommonSlowPaths::arityCheckFor(exec, &vm.interpreter->stack(), CodeForConstruct);
195     if (slotsToAdd < 0) {
196         exec = exec->callerFrame();
197         ErrorHandlingScope errorScope(exec->vm());
198         CommonSlowPaths::interpreterThrowInCaller(exec, createStackOverflowError(exec));
199         RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
200     }
201     RETURN_TWO(0, setupArityCheckData(vm, slotsToAdd));
202 }
203
204 SLOW_PATH_DECL(slow_path_create_direct_arguments)
205 {
206     BEGIN();
207     RETURN(DirectArguments::createByCopying(exec));
208 }
209
210 SLOW_PATH_DECL(slow_path_create_scoped_arguments)
211 {
212     BEGIN();
213     JSLexicalEnvironment* scope = jsCast<JSLexicalEnvironment*>(OP(2).jsValue());
214     ScopedArgumentsTable* table = scope->symbolTable()->arguments();
215     RETURN(ScopedArguments::createByCopying(exec, table, scope));
216 }
217
218 SLOW_PATH_DECL(slow_path_create_cloned_arguments)
219 {
220     BEGIN();
221     RETURN(ClonedArguments::createWithMachineFrame(exec, exec, ArgumentsMode::Cloned));
222 }
223
224 SLOW_PATH_DECL(slow_path_create_this)
225 {
226     BEGIN();
227     JSObject* result;
228     JSObject* constructorAsObject = asObject(OP(2).jsValue());
229     if (constructorAsObject->type() == JSFunctionType) {
230         JSFunction* constructor = jsCast<JSFunction*>(constructorAsObject);
231         auto& cacheWriteBarrier = pc[4].u.jsCell;
232         if (!cacheWriteBarrier)
233             cacheWriteBarrier.set(exec->vm(), exec->codeBlock(), constructor);
234         else if (cacheWriteBarrier.unvalidatedGet() != JSCell::seenMultipleCalleeObjects() && cacheWriteBarrier.get() != constructor)
235             cacheWriteBarrier.setWithoutWriteBarrier(JSCell::seenMultipleCalleeObjects());
236
237         size_t inlineCapacity = pc[3].u.operand;
238         Structure* structure = constructor->rareData(exec, inlineCapacity)->objectAllocationProfile()->structure();
239         result = constructEmptyObject(exec, structure);
240     } else {
241         // http://ecma-international.org/ecma-262/6.0/#sec-ordinarycreatefromconstructor
242         JSValue proto = constructorAsObject->get(exec, exec->propertyNames().prototype);
243         CHECK_EXCEPTION();
244         if (proto.isObject())
245             result = constructEmptyObject(exec, asObject(proto));
246         else
247             result = constructEmptyObject(exec);
248     }
249     RETURN(result);
250 }
251
252 SLOW_PATH_DECL(slow_path_to_this)
253 {
254     BEGIN();
255     JSValue v1 = OP(1).jsValue();
256     if (v1.isCell()) {
257         Structure* myStructure = v1.asCell()->structure(vm);
258         Structure* otherStructure = pc[2].u.structure.get();
259         if (myStructure != otherStructure) {
260             if (otherStructure)
261                 pc[3].u.toThisStatus = ToThisConflicted;
262             pc[2].u.structure.set(vm, exec->codeBlock(), myStructure);
263         }
264     } else {
265         pc[3].u.toThisStatus = ToThisConflicted;
266         pc[2].u.structure.clear();
267     }
268     RETURN(v1.toThis(exec, exec->codeBlock()->isStrictMode() ? StrictMode : NotStrictMode));
269 }
270
271 SLOW_PATH_DECL(slow_path_throw_tdz_error)
272 {
273     BEGIN();
274     THROW(createTDZError(exec));
275 }
276
277 SLOW_PATH_DECL(slow_path_throw_strict_mode_readonly_property_write_error)
278 {
279     BEGIN();
280     THROW(createTypeError(exec, ASCIILiteral(StrictModeReadonlyPropertyWriteError)));
281 }
282
283 SLOW_PATH_DECL(slow_path_not)
284 {
285     BEGIN();
286     RETURN(jsBoolean(!OP_C(2).jsValue().toBoolean(exec)));
287 }
288
289 SLOW_PATH_DECL(slow_path_eq)
290 {
291     BEGIN();
292     RETURN(jsBoolean(JSValue::equal(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
293 }
294
295 SLOW_PATH_DECL(slow_path_neq)
296 {
297     BEGIN();
298     RETURN(jsBoolean(!JSValue::equal(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
299 }
300
301 SLOW_PATH_DECL(slow_path_stricteq)
302 {
303     BEGIN();
304     RETURN(jsBoolean(JSValue::strictEqual(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
305 }
306
307 SLOW_PATH_DECL(slow_path_nstricteq)
308 {
309     BEGIN();
310     RETURN(jsBoolean(!JSValue::strictEqual(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
311 }
312
313 SLOW_PATH_DECL(slow_path_less)
314 {
315     BEGIN();
316     RETURN(jsBoolean(jsLess<true>(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
317 }
318
319 SLOW_PATH_DECL(slow_path_lesseq)
320 {
321     BEGIN();
322     RETURN(jsBoolean(jsLessEq<true>(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
323 }
324
325 SLOW_PATH_DECL(slow_path_greater)
326 {
327     BEGIN();
328     RETURN(jsBoolean(jsLess<false>(exec, OP_C(3).jsValue(), OP_C(2).jsValue())));
329 }
330
331 SLOW_PATH_DECL(slow_path_greatereq)
332 {
333     BEGIN();
334     RETURN(jsBoolean(jsLessEq<false>(exec, OP_C(3).jsValue(), OP_C(2).jsValue())));
335 }
336
337 SLOW_PATH_DECL(slow_path_inc)
338 {
339     BEGIN();
340     RETURN(jsNumber(OP(1).jsValue().toNumber(exec) + 1));
341 }
342
343 SLOW_PATH_DECL(slow_path_dec)
344 {
345     BEGIN();
346     RETURN(jsNumber(OP(1).jsValue().toNumber(exec) - 1));
347 }
348
349 SLOW_PATH_DECL(slow_path_to_string)
350 {
351     BEGIN();
352     RETURN(OP_C(2).jsValue().toString(exec));
353 }
354
355 SLOW_PATH_DECL(slow_path_negate)
356 {
357     BEGIN();
358     RETURN(jsNumber(-OP_C(2).jsValue().toNumber(exec)));
359 }
360
361 #if ENABLE(DFG_JIT)
362 static void updateResultProfileForBinaryArithOp(ExecState* exec, Instruction* pc, JSValue result, JSValue left, JSValue right)
363 {
364     CodeBlock* codeBlock = exec->codeBlock();
365     unsigned bytecodeOffset = codeBlock->bytecodeOffset(pc);
366     ResultProfile* profile = codeBlock->ensureResultProfile(bytecodeOffset);
367
368     if (result.isNumber()) {
369         if (!result.isInt32()) {
370             if (left.isInt32() && right.isInt32())
371                 profile->setObservedInt32Overflow();
372
373             double doubleVal = result.asNumber();
374             if (!doubleVal && std::signbit(doubleVal))
375                 profile->setObservedNegZeroDouble();
376             else {
377                 profile->setObservedNonNegZeroDouble();
378
379                 // The Int52 overflow check here intentionally omits 1ll << 51 as a valid negative Int52 value.
380                 // Therefore, we will get a false positive if the result is that value. This is intentionally
381                 // done to simplify the checking algorithm.
382                 static const int64_t int52OverflowPoint = (1ll << 51);
383                 int64_t int64Val = static_cast<int64_t>(std::abs(doubleVal));
384                 if (int64Val >= int52OverflowPoint)
385                     profile->setObservedInt52Overflow();
386             }
387         }
388     } else
389         profile->setObservedNonNumber();
390 }
391 #else
392 static void updateResultProfileForBinaryArithOp(ExecState*, Instruction*, JSValue, JSValue, JSValue) { }
393 #endif
394
395 SLOW_PATH_DECL(slow_path_to_number)
396 {
397     BEGIN();
398     JSValue argument = OP_C(2).jsValue();
399     JSValue result = jsNumber(argument.toNumber(exec));
400     RETURN_PROFILED(op_to_number, result);
401 }
402
403 SLOW_PATH_DECL(slow_path_add)
404 {
405     BEGIN();
406     JSValue v1 = OP_C(2).jsValue();
407     JSValue v2 = OP_C(3).jsValue();
408     JSValue result;
409
410     if (v1.isString() && !v2.isObject())
411         result = jsString(exec, asString(v1), v2.toString(exec));
412     else if (v1.isNumber() && v2.isNumber())
413         result = jsNumber(v1.asNumber() + v2.asNumber());
414     else
415         result = jsAddSlowCase(exec, v1, v2);
416
417     RETURN_WITH_PROFILING(result, {
418         updateResultProfileForBinaryArithOp(exec, pc, result, v1, v2);
419     });
420 }
421
422 // The following arithmetic and bitwise operations need to be sure to run
423 // toNumber() on their operands in order.  (A call to toNumber() is idempotent
424 // if an exception is already set on the ExecState.)
425
426 SLOW_PATH_DECL(slow_path_mul)
427 {
428     BEGIN();
429     JSValue left = OP_C(2).jsValue();
430     JSValue right = OP_C(3).jsValue();
431     double a = left.toNumber(exec);
432     double b = right.toNumber(exec);
433     JSValue result = jsNumber(a * b);
434     RETURN_WITH_PROFILING(result, {
435         updateResultProfileForBinaryArithOp(exec, pc, result, left, right);
436     });
437 }
438
439 SLOW_PATH_DECL(slow_path_sub)
440 {
441     BEGIN();
442     JSValue left = OP_C(2).jsValue();
443     JSValue right = OP_C(3).jsValue();
444     double a = left.toNumber(exec);
445     double b = right.toNumber(exec);
446     JSValue result = jsNumber(a - b);
447     RETURN_WITH_PROFILING(result, {
448         updateResultProfileForBinaryArithOp(exec, pc, result, left, right);
449     });
450 }
451
452 SLOW_PATH_DECL(slow_path_div)
453 {
454     BEGIN();
455     JSValue left = OP_C(2).jsValue();
456     JSValue right = OP_C(3).jsValue();
457     double a = left.toNumber(exec);
458     double b = right.toNumber(exec);
459     JSValue result = jsNumber(a / b);
460     RETURN_WITH_PROFILING(result, {
461         updateResultProfileForBinaryArithOp(exec, pc, result, left, right);
462     });
463 }
464
465 SLOW_PATH_DECL(slow_path_mod)
466 {
467     BEGIN();
468     double a = OP_C(2).jsValue().toNumber(exec);
469     double b = OP_C(3).jsValue().toNumber(exec);
470     RETURN(jsNumber(jsMod(a, b)));
471 }
472
473 SLOW_PATH_DECL(slow_path_lshift)
474 {
475     BEGIN();
476     int32_t a = OP_C(2).jsValue().toInt32(exec);
477     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
478     RETURN(jsNumber(a << (b & 31)));
479 }
480
481 SLOW_PATH_DECL(slow_path_rshift)
482 {
483     BEGIN();
484     int32_t a = OP_C(2).jsValue().toInt32(exec);
485     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
486     RETURN(jsNumber(a >> (b & 31)));
487 }
488
489 SLOW_PATH_DECL(slow_path_urshift)
490 {
491     BEGIN();
492     uint32_t a = OP_C(2).jsValue().toUInt32(exec);
493     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
494     RETURN(jsNumber(static_cast<int32_t>(a >> (b & 31))));
495 }
496
497 SLOW_PATH_DECL(slow_path_unsigned)
498 {
499     BEGIN();
500     uint32_t a = OP_C(2).jsValue().toUInt32(exec);
501     RETURN(jsNumber(a));
502 }
503
504 SLOW_PATH_DECL(slow_path_bitand)
505 {
506     BEGIN();
507     int32_t a = OP_C(2).jsValue().toInt32(exec);
508     int32_t b = OP_C(3).jsValue().toInt32(exec);
509     RETURN(jsNumber(a & b));
510 }
511
512 SLOW_PATH_DECL(slow_path_bitor)
513 {
514     BEGIN();
515     int32_t a = OP_C(2).jsValue().toInt32(exec);
516     int32_t b = OP_C(3).jsValue().toInt32(exec);
517     RETURN(jsNumber(a | b));
518 }
519
520 SLOW_PATH_DECL(slow_path_bitxor)
521 {
522     BEGIN();
523     int32_t a = OP_C(2).jsValue().toInt32(exec);
524     int32_t b = OP_C(3).jsValue().toInt32(exec);
525     RETURN(jsNumber(a ^ b));
526 }
527
528 SLOW_PATH_DECL(slow_path_typeof)
529 {
530     BEGIN();
531     RETURN(jsTypeStringForValue(exec, OP_C(2).jsValue()));
532 }
533
534 SLOW_PATH_DECL(slow_path_is_object_or_null)
535 {
536     BEGIN();
537     RETURN(jsBoolean(jsIsObjectTypeOrNull(exec, OP_C(2).jsValue())));
538 }
539
540 SLOW_PATH_DECL(slow_path_is_function)
541 {
542     BEGIN();
543     RETURN(jsBoolean(jsIsFunctionType(OP_C(2).jsValue())));
544 }
545
546 SLOW_PATH_DECL(slow_path_in)
547 {
548     BEGIN();
549     RETURN(jsBoolean(CommonSlowPaths::opIn(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
550 }
551
552 SLOW_PATH_DECL(slow_path_del_by_val)
553 {
554     BEGIN();
555     JSValue baseValue = OP_C(2).jsValue();
556     JSObject* baseObject = baseValue.toObject(exec);
557     CHECK_EXCEPTION();
558     
559     JSValue subscript = OP_C(3).jsValue();
560     
561     bool couldDelete;
562     
563     uint32_t i;
564     if (subscript.getUInt32(i))
565         couldDelete = baseObject->methodTable()->deletePropertyByIndex(baseObject, exec, i);
566     else {
567         CHECK_EXCEPTION();
568         auto property = subscript.toPropertyKey(exec);
569         CHECK_EXCEPTION();
570         couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, property);
571     }
572     
573     if (!couldDelete && exec->codeBlock()->isStrictMode())
574         THROW(createTypeError(exec, "Unable to delete property."));
575     
576     RETURN(jsBoolean(couldDelete));
577 }
578
579 SLOW_PATH_DECL(slow_path_strcat)
580 {
581     BEGIN();
582     RETURN(jsStringFromRegisterArray(exec, &OP(2), pc[3].u.operand));
583 }
584
585 SLOW_PATH_DECL(slow_path_to_primitive)
586 {
587     BEGIN();
588     RETURN(OP_C(2).jsValue().toPrimitive(exec));
589 }
590
591 SLOW_PATH_DECL(slow_path_enter)
592 {
593     BEGIN();
594     CodeBlock* codeBlock = exec->codeBlock();
595     Heap::heap(codeBlock)->writeBarrier(codeBlock);
596     END();
597 }
598
599 SLOW_PATH_DECL(slow_path_get_enumerable_length)
600 {
601     BEGIN();
602     JSValue enumeratorValue = OP(2).jsValue();
603     if (enumeratorValue.isUndefinedOrNull())
604         RETURN(jsNumber(0));
605
606     JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(enumeratorValue.asCell());
607
608     RETURN(jsNumber(enumerator->indexedLength()));
609 }
610
611 SLOW_PATH_DECL(slow_path_has_indexed_property)
612 {
613     BEGIN();
614     JSObject* base = OP(2).jsValue().toObject(exec);
615     CHECK_EXCEPTION();
616     JSValue property = OP(3).jsValue();
617     pc[4].u.arrayProfile->observeStructure(base->structure(vm));
618     ASSERT(property.isUInt32());
619     RETURN(jsBoolean(base->hasPropertyGeneric(exec, property.asUInt32(), PropertySlot::InternalMethodType::GetOwnProperty)));
620 }
621
622 SLOW_PATH_DECL(slow_path_has_structure_property)
623 {
624     BEGIN();
625     JSObject* base = OP(2).jsValue().toObject(exec);
626     CHECK_EXCEPTION();
627     JSValue property = OP(3).jsValue();
628     ASSERT(property.isString());
629     JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(OP(4).jsValue().asCell());
630     if (base->structure(vm)->id() == enumerator->cachedStructureID())
631         RETURN(jsBoolean(true));
632     RETURN(jsBoolean(base->hasPropertyGeneric(exec, asString(property.asCell())->toIdentifier(exec), PropertySlot::InternalMethodType::GetOwnProperty)));
633 }
634
635 SLOW_PATH_DECL(slow_path_has_generic_property)
636 {
637     BEGIN();
638     JSObject* base = OP(2).jsValue().toObject(exec);
639     CHECK_EXCEPTION();
640     JSValue property = OP(3).jsValue();
641     bool result;
642     if (property.isString())
643         result = base->hasPropertyGeneric(exec, asString(property.asCell())->toIdentifier(exec), PropertySlot::InternalMethodType::GetOwnProperty);
644     else {
645         ASSERT(property.isUInt32());
646         result = base->hasPropertyGeneric(exec, property.asUInt32(), PropertySlot::InternalMethodType::GetOwnProperty);
647     }
648     RETURN(jsBoolean(result));
649 }
650
651 SLOW_PATH_DECL(slow_path_get_direct_pname)
652 {
653     BEGIN();
654     JSValue baseValue = OP_C(2).jsValue();
655     JSValue property = OP(3).jsValue();
656     ASSERT(property.isString());
657     RETURN(baseValue.get(exec, asString(property)->toIdentifier(exec)));
658 }
659
660 SLOW_PATH_DECL(slow_path_get_property_enumerator)
661 {
662     BEGIN();
663     JSValue baseValue = OP(2).jsValue();
664     if (baseValue.isUndefinedOrNull())
665         RETURN(JSPropertyNameEnumerator::create(vm));
666
667     JSObject* base = baseValue.toObject(exec);
668     CHECK_EXCEPTION();
669
670     RETURN(propertyNameEnumerator(exec, base));
671 }
672
673 SLOW_PATH_DECL(slow_path_next_structure_enumerator_pname)
674 {
675     BEGIN();
676     JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(OP(2).jsValue().asCell());
677     uint32_t index = OP(3).jsValue().asUInt32();
678
679     JSString* propertyName = nullptr;
680     if (index < enumerator->endStructurePropertyIndex())
681         propertyName = enumerator->propertyNameAtIndex(index);
682     RETURN(propertyName ? propertyName : jsNull());
683 }
684
685 SLOW_PATH_DECL(slow_path_next_generic_enumerator_pname)
686 {
687     BEGIN();
688     JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(OP(2).jsValue().asCell());
689     uint32_t index = OP(3).jsValue().asUInt32();
690
691     JSString* propertyName = nullptr;
692     if (enumerator->endStructurePropertyIndex() <= index && index < enumerator->endGenericPropertyIndex())
693         propertyName = enumerator->propertyNameAtIndex(index);
694     RETURN(propertyName ? propertyName : jsNull());
695 }
696
697 SLOW_PATH_DECL(slow_path_to_index_string)
698 {
699     BEGIN();
700     RETURN(jsString(exec, Identifier::from(exec, OP(2).jsValue().asUInt32()).string()));
701 }
702
703 SLOW_PATH_DECL(slow_path_profile_type_clear_log)
704 {
705     BEGIN();
706     vm.typeProfilerLog()->processLogEntries(ASCIILiteral("LLInt log full."));
707     END();
708 }
709
710 SLOW_PATH_DECL(slow_path_assert)
711 {
712     BEGIN();
713     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());
714     END();
715 }
716
717 SLOW_PATH_DECL(slow_path_save)
718 {
719     // Only save variables and temporary registers. The scope registers are included in them.
720     // But parameters are not included. Because the generator implementation replaces the values of parameters on each generator.next() call.
721     BEGIN();
722     JSValue generator = OP(1).jsValue();
723     GeneratorFrame* frame = nullptr;
724     JSValue value = generator.get(exec, exec->propertyNames().builtinNames().generatorFramePrivateName());
725     if (!value.isNull())
726         frame = jsCast<GeneratorFrame*>(value);
727     else {
728         // FIXME: Once JSGenerator specialized object is introduced, this GeneratorFrame should be embeded into it to avoid allocations.
729         // https://bugs.webkit.org/show_bug.cgi?id=151545
730         frame = GeneratorFrame::create(exec->vm(),  exec->codeBlock()->numCalleeLocals());
731         PutPropertySlot slot(generator, true, PutPropertySlot::PutById);
732         asObject(generator)->methodTable(exec->vm())->put(asObject(generator), exec, exec->propertyNames().builtinNames().generatorFramePrivateName(), frame, slot);
733     }
734     unsigned liveCalleeLocalsIndex = pc[2].u.unsignedValue;
735     frame->save(exec, exec->codeBlock()->liveCalleeLocalsAtYield(liveCalleeLocalsIndex));
736     END();
737 }
738
739 SLOW_PATH_DECL(slow_path_resume)
740 {
741     BEGIN();
742     JSValue generator = OP(1).jsValue();
743     GeneratorFrame* frame = jsCast<GeneratorFrame*>(generator.get(exec, exec->propertyNames().builtinNames().generatorFramePrivateName()));
744     unsigned liveCalleeLocalsIndex = pc[2].u.unsignedValue;
745     frame->resume(exec, exec->codeBlock()->liveCalleeLocalsAtYield(liveCalleeLocalsIndex));
746     END();
747 }
748
749 SLOW_PATH_DECL(slow_path_create_lexical_environment)
750 {
751     BEGIN();
752     int scopeReg = pc[2].u.operand;
753     JSScope* currentScope = exec->uncheckedR(scopeReg).Register::scope();
754     SymbolTable* symbolTable = jsCast<SymbolTable*>(OP_C(3).jsValue());
755     JSValue initialValue = OP_C(4).jsValue();
756     ASSERT(initialValue == jsUndefined() || initialValue == jsTDZValue());
757     JSScope* newScope = JSLexicalEnvironment::create(vm, exec->lexicalGlobalObject(), currentScope, symbolTable, initialValue);
758     RETURN(newScope);
759 }
760
761 SLOW_PATH_DECL(slow_path_push_with_scope)
762 {
763     BEGIN();
764     JSObject* newScope = OP_C(2).jsValue().toObject(exec);
765     CHECK_EXCEPTION();
766
767     int scopeReg = pc[3].u.operand;
768     JSScope* currentScope = exec->uncheckedR(scopeReg).Register::scope();
769     RETURN(JSWithScope::create(vm, exec->lexicalGlobalObject(), newScope, currentScope));
770 }
771
772 SLOW_PATH_DECL(slow_path_resolve_scope)
773 {
774     BEGIN();
775     const Identifier& ident = exec->codeBlock()->identifier(pc[3].u.operand);
776     JSScope* scope = exec->uncheckedR(pc[2].u.operand).Register::scope();
777     JSObject* resolvedScope = JSScope::resolve(exec, scope, ident);
778     // Proxy can throw an error here, e.g. Proxy in with statement's @unscopables.
779     CHECK_EXCEPTION();
780
781     ResolveType resolveType = static_cast<ResolveType>(pc[4].u.operand);
782
783     // ModuleVar does not keep the scope register value alive in DFG.
784     ASSERT(resolveType != ModuleVar);
785
786     if (resolveType == UnresolvedProperty || resolveType == UnresolvedPropertyWithVarInjectionChecks) {
787         if (resolvedScope->isGlobalObject()) {
788             JSGlobalObject* globalObject = jsCast<JSGlobalObject*>(resolvedScope);
789             if (globalObject->hasProperty(exec, ident)) {
790                 ConcurrentJITLocker locker(exec->codeBlock()->m_lock);
791                 if (resolveType == UnresolvedProperty)
792                     pc[4].u.operand = GlobalProperty;
793                 else
794                     pc[4].u.operand = GlobalPropertyWithVarInjectionChecks;
795
796                 pc[6].u.pointer = globalObject;
797             }
798         } else if (resolvedScope->isGlobalLexicalEnvironment()) {
799             JSGlobalLexicalEnvironment* globalLexicalEnvironment = jsCast<JSGlobalLexicalEnvironment*>(resolvedScope);
800             ConcurrentJITLocker locker(exec->codeBlock()->m_lock);
801             if (resolveType == UnresolvedProperty)
802                 pc[4].u.operand = GlobalLexicalVar;
803             else
804                 pc[4].u.operand = GlobalLexicalVarWithVarInjectionChecks;
805             pc[6].u.pointer = globalLexicalEnvironment;
806         }
807     }
808
809     RETURN(resolvedScope);
810 }
811
812 SLOW_PATH_DECL(slow_path_copy_rest)
813 {
814     BEGIN();
815     unsigned arraySize = OP_C(2).jsValue().asUInt32();
816     if (!arraySize) {
817         ASSERT(!jsCast<JSArray*>(OP(1).jsValue())->length());
818         END();
819     }
820     JSArray* array = jsCast<JSArray*>(OP(1).jsValue());
821     ASSERT(arraySize == array->length());
822     unsigned numParamsToSkip = pc[3].u.unsignedValue;
823     for (unsigned i = 0; i < arraySize; i++)
824         array->putDirectIndex(exec, i, exec->uncheckedArgument(i + numParamsToSkip));
825     END();
826 }
827
828 SLOW_PATH_DECL(slow_path_get_by_id_with_this)
829 {
830     BEGIN();
831     const Identifier& ident = exec->codeBlock()->identifier(pc[4].u.operand);
832     JSValue baseValue = OP_C(2).jsValue();
833     JSValue thisVal = OP_C(3).jsValue();
834     PropertySlot slot(thisVal, PropertySlot::PropertySlot::InternalMethodType::Get);
835     JSValue result = baseValue.get(exec, ident, slot);
836     RETURN(result);
837 }
838
839 SLOW_PATH_DECL(slow_path_get_by_val_with_this)
840 {
841     BEGIN();
842
843     JSValue baseValue = OP_C(2).jsValue();
844     JSValue thisValue = OP_C(3).jsValue();
845     JSValue subscript = OP_C(4).jsValue();
846
847     if (LIKELY(baseValue.isCell() && subscript.isString())) {
848         VM& vm = exec->vm();
849         Structure& structure = *baseValue.asCell()->structure(vm);
850         if (JSCell::canUseFastGetOwnProperty(structure)) {
851             if (RefPtr<AtomicStringImpl> existingAtomicString = asString(subscript)->toExistingAtomicString(exec)) {
852                 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
853                     RETURN(result); 
854             }
855         }
856     }
857     
858     PropertySlot slot(thisValue, PropertySlot::PropertySlot::InternalMethodType::Get);
859     if (subscript.isUInt32()) {
860         uint32_t i = subscript.asUInt32();
861         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
862             RETURN(asString(baseValue)->getIndex(exec, i));
863         
864         RETURN(baseValue.get(exec, i, slot));
865     }
866
867     baseValue.requireObjectCoercible(exec);
868     CHECK_EXCEPTION();
869     auto property = subscript.toPropertyKey(exec);
870     CHECK_EXCEPTION();
871     RETURN(baseValue.get(exec, property, slot));
872 }
873
874 SLOW_PATH_DECL(slow_path_put_by_id_with_this)
875 {
876     BEGIN();
877     CodeBlock* codeBlock = exec->codeBlock();
878     const Identifier& ident = codeBlock->identifier(pc[3].u.operand);
879     JSValue baseValue = OP_C(1).jsValue();
880     JSValue thisVal = OP_C(2).jsValue();
881     JSValue putValue = OP_C(4).jsValue();
882     PutPropertySlot slot(thisVal, codeBlock->isStrictMode(), codeBlock->putByIdContext());
883     baseValue.putInline(exec, ident, putValue, slot);
884     END();
885 }
886
887 SLOW_PATH_DECL(slow_path_put_by_val_with_this)
888 {
889     BEGIN();
890     JSValue baseValue = OP_C(1).jsValue();
891     JSValue thisValue = OP_C(2).jsValue();
892     JSValue subscript = OP_C(3).jsValue();
893     JSValue value = OP_C(4).jsValue();
894     
895     auto property = subscript.toPropertyKey(exec);
896     CHECK_EXCEPTION();
897     PutPropertySlot slot(thisValue, exec->codeBlock()->isStrictMode());
898     baseValue.put(exec, property, value, slot);
899     END();
900 }
901
902 } // namespace JSC