JSC should detect singleton functions
[WebKit-https.git] / Source / JavaScriptCore / jit / JITOperations.cpp
1 /*
2  * Copyright (C) 2013-2015 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 "JITOperations.h"
28
29 #if ENABLE(JIT)
30
31 #include "ArrayConstructor.h"
32 #include "DFGCompilationMode.h"
33 #include "DFGDriver.h"
34 #include "DFGOSREntry.h"
35 #include "DFGThunks.h"
36 #include "DFGWorklist.h"
37 #include "Debugger.h"
38 #include "Error.h"
39 #include "ErrorHandlingScope.h"
40 #include "ExceptionFuzz.h"
41 #include "GetterSetter.h"
42 #include "HostCallReturnValue.h"
43 #include "JIT.h"
44 #include "JITToDFGDeferredCompilationCallback.h"
45 #include "JSCInlines.h"
46 #include "JSCatchScope.h"
47 #include "JSFunctionNameScope.h"
48 #include "JSGlobalObjectFunctions.h"
49 #include "JSLexicalEnvironment.h"
50 #include "JSNameScope.h"
51 #include "JSPropertyNameEnumerator.h"
52 #include "JSStackInlines.h"
53 #include "JSWithScope.h"
54 #include "LegacyProfiler.h"
55 #include "ObjectConstructor.h"
56 #include "PropertyName.h"
57 #include "Repatch.h"
58 #include "RepatchBuffer.h"
59 #include "TestRunnerUtils.h"
60 #include "TypeProfilerLog.h"
61 #include <wtf/InlineASM.h>
62
63 namespace JSC {
64
65 template<typename ScopeType>
66 void pushNameScope(ExecState* exec, int32_t dst, SymbolTable* symbolTable, EncodedJSValue encodedValue)
67 {
68     VM& vm = exec->vm();
69     NativeCallFrameTracer tracer(&vm, exec);
70     
71     ASSERT(!JITCode::isOptimizingJIT(exec->codeBlock()->jitType()));
72
73     // FIXME: This won't work if this operation is called from the DFG or FTL.
74     // This should be changed to pass in the new scope.
75     JSScope* currentScope = exec->uncheckedR(dst).Register::scope();
76     JSNameScope* scope = ScopeType::create(vm, exec->lexicalGlobalObject(), currentScope, symbolTable, JSValue::decode(encodedValue));
77
78     // FIXME: This won't work if this operation is called from the DFG or FTL.
79     // This should be changed to return the new scope.
80     exec->uncheckedR(dst) = scope;
81 }
82
83 extern "C" {
84
85 #if COMPILER(MSVC)
86 void * _ReturnAddress(void);
87 #pragma intrinsic(_ReturnAddress)
88
89 #define OUR_RETURN_ADDRESS _ReturnAddress()
90 #else
91 #define OUR_RETURN_ADDRESS __builtin_return_address(0)
92 #endif
93
94 #if ENABLE(OPCODE_SAMPLING)
95 #define CTI_SAMPLER vm->interpreter->sampler()
96 #else
97 #define CTI_SAMPLER 0
98 #endif
99
100
101 void JIT_OPERATION operationThrowStackOverflowError(ExecState* exec, CodeBlock* codeBlock)
102 {
103     // We pass in our own code block, because the callframe hasn't been populated.
104     VM* vm = codeBlock->vm();
105
106     VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
107     CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
108     if (!callerFrame)
109         callerFrame = exec;
110
111     NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
112     ErrorHandlingScope errorScope(*vm);
113     vm->throwException(callerFrame, createStackOverflowError(callerFrame));
114 }
115
116 int32_t JIT_OPERATION operationCallArityCheck(ExecState* exec)
117 {
118     VM* vm = &exec->vm();
119     VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
120     CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
121
122     JSStack& stack = vm->interpreter->stack();
123
124     int32_t missingArgCount = CommonSlowPaths::arityCheckFor(exec, &stack, CodeForCall);
125     if (missingArgCount < 0) {
126         NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
127         throwStackOverflowError(callerFrame);
128     }
129
130     return missingArgCount;
131 }
132
133 int32_t JIT_OPERATION operationConstructArityCheck(ExecState* exec)
134 {
135     VM* vm = &exec->vm();
136     VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
137     CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
138
139     JSStack& stack = vm->interpreter->stack();
140
141     int32_t missingArgCount = CommonSlowPaths::arityCheckFor(exec, &stack, CodeForConstruct);
142     if (missingArgCount < 0) {
143         NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
144         throwStackOverflowError(callerFrame);
145     }
146
147     return missingArgCount;
148 }
149
150 EncodedJSValue JIT_OPERATION operationGetById(ExecState* exec, StructureStubInfo*, EncodedJSValue base, StringImpl* uid)
151 {
152     VM* vm = &exec->vm();
153     NativeCallFrameTracer tracer(vm, exec);
154     
155     JSValue baseValue = JSValue::decode(base);
156     PropertySlot slot(baseValue);
157     Identifier ident = Identifier::fromUid(vm, uid);
158     return JSValue::encode(baseValue.get(exec, ident, slot));
159 }
160
161 EncodedJSValue JIT_OPERATION operationGetByIdBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, StringImpl* uid)
162 {
163     VM* vm = &exec->vm();
164     NativeCallFrameTracer tracer(vm, exec);
165
166     Identifier ident = Identifier::fromUid(vm, uid);
167     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
168
169     JSValue baseValue = JSValue::decode(base);
170     PropertySlot slot(baseValue);
171     bool hasResult = baseValue.getPropertySlot(exec, ident, slot);
172     
173     if (accessType == static_cast<AccessType>(stubInfo->accessType))
174         buildGetByIDList(exec, baseValue, ident, slot, *stubInfo);
175
176     return JSValue::encode(hasResult? slot.getValue(exec, ident) : jsUndefined());
177 }
178
179 EncodedJSValue JIT_OPERATION operationGetByIdOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, StringImpl* uid)
180 {
181     VM* vm = &exec->vm();
182     NativeCallFrameTracer tracer(vm, exec);
183     Identifier ident = Identifier::fromUid(vm, uid);
184
185     JSValue baseValue = JSValue::decode(base);
186     PropertySlot slot(baseValue);
187     
188     bool hasResult = baseValue.getPropertySlot(exec, ident, slot);
189     if (stubInfo->seen)
190         repatchGetByID(exec, baseValue, ident, slot, *stubInfo);
191     else
192         stubInfo->seen = true;
193     
194     return JSValue::encode(hasResult? slot.getValue(exec, ident) : jsUndefined());
195
196 }
197
198 EncodedJSValue JIT_OPERATION operationInOptimize(ExecState* exec, StructureStubInfo* stubInfo, JSCell* base, StringImpl* key)
199 {
200     VM* vm = &exec->vm();
201     NativeCallFrameTracer tracer(vm, exec);
202     
203     if (!base->isObject()) {
204         vm->throwException(exec, createInvalidInParameterError(exec, base));
205         return JSValue::encode(jsUndefined());
206     }
207     
208     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
209
210     Identifier ident = Identifier::fromUid(vm, key);
211     PropertySlot slot(base);
212     bool result = asObject(base)->getPropertySlot(exec, ident, slot);
213     
214     RELEASE_ASSERT(accessType == stubInfo->accessType);
215     
216     if (stubInfo->seen)
217         repatchIn(exec, base, ident, result, slot, *stubInfo);
218     else
219         stubInfo->seen = true;
220     
221     return JSValue::encode(jsBoolean(result));
222 }
223
224 EncodedJSValue JIT_OPERATION operationIn(ExecState* exec, StructureStubInfo*, JSCell* base, StringImpl* key)
225 {
226     VM* vm = &exec->vm();
227     NativeCallFrameTracer tracer(vm, exec);
228
229     if (!base->isObject()) {
230         vm->throwException(exec, createInvalidInParameterError(exec, base));
231         return JSValue::encode(jsUndefined());
232     }
233
234     Identifier ident = Identifier::fromUid(vm, key);
235     return JSValue::encode(jsBoolean(asObject(base)->hasProperty(exec, ident)));
236 }
237
238 EncodedJSValue JIT_OPERATION operationGenericIn(ExecState* exec, JSCell* base, EncodedJSValue key)
239 {
240     VM* vm = &exec->vm();
241     NativeCallFrameTracer tracer(vm, exec);
242
243     return JSValue::encode(jsBoolean(CommonSlowPaths::opIn(exec, JSValue::decode(key), base)));
244 }
245
246 void JIT_OPERATION operationPutByIdStrict(ExecState* exec, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
247 {
248     VM* vm = &exec->vm();
249     NativeCallFrameTracer tracer(vm, exec);
250     
251     Identifier ident = Identifier::fromUid(vm, uid);
252     PutPropertySlot slot(JSValue::decode(encodedBase), true, exec->codeBlock()->putByIdContext());
253     JSValue::decode(encodedBase).put(exec, ident, JSValue::decode(encodedValue), slot);
254 }
255
256 void JIT_OPERATION operationPutByIdNonStrict(ExecState* exec, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
257 {
258     VM* vm = &exec->vm();
259     NativeCallFrameTracer tracer(vm, exec);
260     
261     Identifier ident = Identifier::fromUid(vm, uid);
262     PutPropertySlot slot(JSValue::decode(encodedBase), false, exec->codeBlock()->putByIdContext());
263     JSValue::decode(encodedBase).put(exec, ident, JSValue::decode(encodedValue), slot);
264 }
265
266 void JIT_OPERATION operationPutByIdDirectStrict(ExecState* exec, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
267 {
268     VM* vm = &exec->vm();
269     NativeCallFrameTracer tracer(vm, exec);
270     
271     Identifier ident = Identifier::fromUid(vm, uid);
272     PutPropertySlot slot(JSValue::decode(encodedBase), true, exec->codeBlock()->putByIdContext());
273     asObject(JSValue::decode(encodedBase))->putDirect(exec->vm(), ident, JSValue::decode(encodedValue), slot);
274 }
275
276 void JIT_OPERATION operationPutByIdDirectNonStrict(ExecState* exec, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
277 {
278     VM* vm = &exec->vm();
279     NativeCallFrameTracer tracer(vm, exec);
280     
281     Identifier ident = Identifier::fromUid(vm, uid);
282     PutPropertySlot slot(JSValue::decode(encodedBase), false, exec->codeBlock()->putByIdContext());
283     asObject(JSValue::decode(encodedBase))->putDirect(exec->vm(), ident, JSValue::decode(encodedValue), slot);
284 }
285
286 void JIT_OPERATION operationPutByIdStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
287 {
288     VM* vm = &exec->vm();
289     NativeCallFrameTracer tracer(vm, exec);
290     
291     Identifier ident = Identifier::fromUid(vm, uid);
292     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
293
294     JSValue value = JSValue::decode(encodedValue);
295     JSValue baseValue = JSValue::decode(encodedBase);
296     PutPropertySlot slot(baseValue, true, exec->codeBlock()->putByIdContext());
297
298     Structure* structure = baseValue.isCell() ? baseValue.asCell()->structure(*vm) : nullptr;
299     baseValue.put(exec, ident, value, slot);
300     
301     if (accessType != static_cast<AccessType>(stubInfo->accessType))
302         return;
303     
304     if (stubInfo->seen)
305         repatchPutByID(exec, baseValue, structure, ident, slot, *stubInfo, NotDirect);
306     else
307         stubInfo->seen = true;
308 }
309
310 void JIT_OPERATION operationPutByIdNonStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
311 {
312     VM* vm = &exec->vm();
313     NativeCallFrameTracer tracer(vm, exec);
314     
315     Identifier ident = Identifier::fromUid(vm, uid);
316     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
317
318     JSValue value = JSValue::decode(encodedValue);
319     JSValue baseValue = JSValue::decode(encodedBase);
320     PutPropertySlot slot(baseValue, false, exec->codeBlock()->putByIdContext());
321
322     Structure* structure = baseValue.isCell() ? baseValue.asCell()->structure(*vm) : nullptr;    
323     baseValue.put(exec, ident, value, slot);
324     
325     if (accessType != static_cast<AccessType>(stubInfo->accessType))
326         return;
327     
328     if (stubInfo->seen)
329         repatchPutByID(exec, baseValue, structure, ident, slot, *stubInfo, NotDirect);
330     else
331         stubInfo->seen = true;
332 }
333
334 void JIT_OPERATION operationPutByIdDirectStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
335 {
336     VM* vm = &exec->vm();
337     NativeCallFrameTracer tracer(vm, exec);
338     
339     Identifier ident = Identifier::fromUid(vm, uid);
340     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
341
342     JSValue value = JSValue::decode(encodedValue);
343     JSObject* baseObject = asObject(JSValue::decode(encodedBase));
344     PutPropertySlot slot(baseObject, true, exec->codeBlock()->putByIdContext());
345     
346     Structure* structure = baseObject->structure(*vm);
347     baseObject->putDirect(exec->vm(), ident, value, slot);
348     
349     if (accessType != static_cast<AccessType>(stubInfo->accessType))
350         return;
351     
352     if (stubInfo->seen)
353         repatchPutByID(exec, baseObject, structure, ident, slot, *stubInfo, Direct);
354     else
355         stubInfo->seen = true;
356 }
357
358 void JIT_OPERATION operationPutByIdDirectNonStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
359 {
360     VM* vm = &exec->vm();
361     NativeCallFrameTracer tracer(vm, exec);
362     
363     Identifier ident = Identifier::fromUid(vm, uid);
364     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
365
366     JSValue value = JSValue::decode(encodedValue);
367     JSObject* baseObject = asObject(JSValue::decode(encodedBase));
368     PutPropertySlot slot(baseObject, false, exec->codeBlock()->putByIdContext());
369     
370     Structure* structure = baseObject->structure(*vm);
371     baseObject->putDirect(exec->vm(), ident, value, slot);
372     
373     if (accessType != static_cast<AccessType>(stubInfo->accessType))
374         return;
375     
376     if (stubInfo->seen)
377         repatchPutByID(exec, baseObject, structure, ident, slot, *stubInfo, Direct);
378     else
379         stubInfo->seen = true;
380 }
381
382 void JIT_OPERATION operationPutByIdStrictBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
383 {
384     VM* vm = &exec->vm();
385     NativeCallFrameTracer tracer(vm, exec);
386     
387     Identifier ident = Identifier::fromUid(vm, uid);
388     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
389
390     JSValue value = JSValue::decode(encodedValue);
391     JSValue baseValue = JSValue::decode(encodedBase);
392     PutPropertySlot slot(baseValue, true, exec->codeBlock()->putByIdContext());
393     
394     Structure* structure = baseValue.isCell() ? baseValue.asCell()->structure(*vm) : nullptr; 
395     baseValue.put(exec, ident, value, slot);
396
397     if (accessType != static_cast<AccessType>(stubInfo->accessType))
398         return;
399
400     buildPutByIdList(exec, baseValue, structure, ident, slot, *stubInfo, NotDirect);
401 }
402
403 void JIT_OPERATION operationPutByIdNonStrictBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
404 {
405     VM* vm = &exec->vm();
406     NativeCallFrameTracer tracer(vm, exec);
407     
408     Identifier ident = Identifier::fromUid(vm, uid);
409     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
410
411     JSValue value = JSValue::decode(encodedValue);
412     JSValue baseValue = JSValue::decode(encodedBase);
413     PutPropertySlot slot(baseValue, false, exec->codeBlock()->putByIdContext());
414
415     Structure* structure = baseValue.isCell() ? baseValue.asCell()->structure(*vm) : nullptr;
416     baseValue.put(exec, ident, value, slot);
417     
418     if (accessType != static_cast<AccessType>(stubInfo->accessType))
419         return;
420     
421     buildPutByIdList(exec, baseValue, structure, ident, slot, *stubInfo, NotDirect);
422 }
423
424 void JIT_OPERATION operationPutByIdDirectStrictBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
425 {
426     VM* vm = &exec->vm();
427     NativeCallFrameTracer tracer(vm, exec);
428     
429     Identifier ident = Identifier::fromUid(vm, uid);
430     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
431     
432     JSValue value = JSValue::decode(encodedValue);
433     JSObject* baseObject = asObject(JSValue::decode(encodedBase));
434     PutPropertySlot slot(baseObject, true, exec->codeBlock()->putByIdContext());
435
436     Structure* structure = baseObject->structure(*vm);    
437     baseObject->putDirect(*vm, ident, value, slot);
438     
439     if (accessType != static_cast<AccessType>(stubInfo->accessType))
440         return;
441     
442     buildPutByIdList(exec, baseObject, structure, ident, slot, *stubInfo, Direct);
443 }
444
445 void JIT_OPERATION operationPutByIdDirectNonStrictBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
446 {
447     VM* vm = &exec->vm();
448     NativeCallFrameTracer tracer(vm, exec);
449     
450     Identifier ident = Identifier::fromUid(vm, uid);
451     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
452
453     JSValue value = JSValue::decode(encodedValue);
454     JSObject* baseObject = asObject(JSValue::decode(encodedBase));
455     PutPropertySlot slot(baseObject, false, exec->codeBlock()->putByIdContext());
456
457     Structure* structure = baseObject->structure(*vm);    
458     baseObject->putDirect(*vm, ident, value, slot);
459
460     if (accessType != static_cast<AccessType>(stubInfo->accessType))
461         return;
462     
463     buildPutByIdList(exec, baseObject, structure, ident, slot, *stubInfo, Direct);
464 }
465
466 void JIT_OPERATION operationReallocateStorageAndFinishPut(ExecState* exec, JSObject* base, Structure* structure, PropertyOffset offset, EncodedJSValue value)
467 {
468     VM& vm = exec->vm();
469     NativeCallFrameTracer tracer(&vm, exec);
470
471     ASSERT(structure->outOfLineCapacity() > base->structure(vm)->outOfLineCapacity());
472     ASSERT(!vm.heap.storageAllocator().fastPathShouldSucceed(structure->outOfLineCapacity() * sizeof(JSValue)));
473     base->setStructureAndReallocateStorageIfNecessary(vm, structure);
474     base->putDirect(vm, offset, JSValue::decode(value));
475 }
476
477 static void putByVal(CallFrame* callFrame, JSValue baseValue, JSValue subscript, JSValue value)
478 {
479     VM& vm = callFrame->vm();
480     if (LIKELY(subscript.isUInt32())) {
481         uint32_t i = subscript.asUInt32();
482         if (baseValue.isObject()) {
483             JSObject* object = asObject(baseValue);
484             if (object->canSetIndexQuickly(i))
485                 object->setIndexQuickly(callFrame->vm(), i, value);
486             else
487                 object->methodTable(vm)->putByIndex(object, callFrame, i, value, callFrame->codeBlock()->isStrictMode());
488         } else
489             baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode());
490     } else {
491         auto property = subscript.toPropertyKey(callFrame);
492         if (!callFrame->vm().exception()) { // Don't put to an object if toString threw an exception.
493             PutPropertySlot slot(baseValue, callFrame->codeBlock()->isStrictMode());
494             baseValue.put(callFrame, property, value, slot);
495         }
496     }
497 }
498
499 static void directPutByVal(CallFrame* callFrame, JSObject* baseObject, JSValue subscript, JSValue value)
500 {
501     bool isStrictMode = callFrame->codeBlock()->isStrictMode();
502     if (LIKELY(subscript.isUInt32())) {
503         // Despite its name, JSValue::isUInt32 will return true only for positive boxed int32_t; all those values are valid array indices.
504         ASSERT(isIndex(subscript.asUInt32()));
505         baseObject->putDirectIndex(callFrame, subscript.asUInt32(), value, 0, isStrictMode ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
506         return;
507     }
508
509     if (subscript.isDouble()) {
510         double subscriptAsDouble = subscript.asDouble();
511         uint32_t subscriptAsUInt32 = static_cast<uint32_t>(subscriptAsDouble);
512         if (subscriptAsDouble == subscriptAsUInt32 && isIndex(subscriptAsUInt32)) {
513             baseObject->putDirectIndex(callFrame, subscriptAsUInt32, value, 0, isStrictMode ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
514             return;
515         }
516     }
517
518     // Don't put to an object if toString threw an exception.
519     auto property = subscript.toPropertyKey(callFrame);
520     if (callFrame->vm().exception())
521         return;
522
523     if (Optional<uint32_t> index = parseIndex(property))
524         baseObject->putDirectIndex(callFrame, index.value(), value, 0, isStrictMode ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
525     else {
526         PutPropertySlot slot(baseObject, isStrictMode);
527         baseObject->putDirect(callFrame->vm(), property, value, slot);
528     }
529 }
530 void JIT_OPERATION operationPutByVal(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
531 {
532     VM& vm = exec->vm();
533     NativeCallFrameTracer tracer(&vm, exec);
534
535     JSValue baseValue = JSValue::decode(encodedBaseValue);
536     JSValue subscript = JSValue::decode(encodedSubscript);
537     JSValue value = JSValue::decode(encodedValue);
538
539     if (baseValue.isObject() && subscript.isInt32()) {
540         // See if it's worth optimizing at all.
541         JSObject* object = asObject(baseValue);
542         bool didOptimize = false;
543
544         unsigned bytecodeOffset = exec->locationAsBytecodeOffset();
545         ASSERT(bytecodeOffset);
546         ByValInfo& byValInfo = exec->codeBlock()->getByValInfo(bytecodeOffset - 1);
547         ASSERT(!byValInfo.stubRoutine);
548
549         if (hasOptimizableIndexing(object->structure(vm))) {
550             // Attempt to optimize.
551             JITArrayMode arrayMode = jitArrayModeForStructure(object->structure(vm));
552             if (jitArrayModePermitsPut(arrayMode) && arrayMode != byValInfo.arrayMode) {
553                 JIT::compilePutByVal(&vm, exec->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
554                 didOptimize = true;
555             }
556         }
557
558         if (!didOptimize) {
559             // If we take slow path more than 10 times without patching then make sure we
560             // never make that mistake again. Or, if we failed to patch and we have some object
561             // that intercepts indexed get, then don't even wait until 10 times. For cases
562             // where we see non-index-intercepting objects, this gives 10 iterations worth of
563             // opportunity for us to observe that the get_by_val may be polymorphic.
564             if (++byValInfo.slowPathCount >= 10
565                 || object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
566                 // Don't ever try to optimize.
567                 ctiPatchCallByReturnAddress(exec->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationPutByValGeneric));
568             }
569         }
570     }
571
572     putByVal(exec, baseValue, subscript, value);
573 }
574
575 void JIT_OPERATION operationDirectPutByVal(ExecState* callFrame, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
576 {
577     VM& vm = callFrame->vm();
578     NativeCallFrameTracer tracer(&vm, callFrame);
579     
580     JSValue baseValue = JSValue::decode(encodedBaseValue);
581     JSValue subscript = JSValue::decode(encodedSubscript);
582     JSValue value = JSValue::decode(encodedValue);
583     RELEASE_ASSERT(baseValue.isObject());
584     JSObject* object = asObject(baseValue);
585     if (subscript.isInt32()) {
586         // See if it's worth optimizing at all.
587         bool didOptimize = false;
588         
589         unsigned bytecodeOffset = callFrame->locationAsBytecodeOffset();
590         ASSERT(bytecodeOffset);
591         ByValInfo& byValInfo = callFrame->codeBlock()->getByValInfo(bytecodeOffset - 1);
592         ASSERT(!byValInfo.stubRoutine);
593         
594         if (hasOptimizableIndexing(object->structure(vm))) {
595             // Attempt to optimize.
596             JITArrayMode arrayMode = jitArrayModeForStructure(object->structure(vm));
597             if (jitArrayModePermitsPut(arrayMode) && arrayMode != byValInfo.arrayMode) {
598                 JIT::compileDirectPutByVal(&vm, callFrame->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
599                 didOptimize = true;
600             }
601         }
602         
603         if (!didOptimize) {
604             // If we take slow path more than 10 times without patching then make sure we
605             // never make that mistake again. Or, if we failed to patch and we have some object
606             // that intercepts indexed get, then don't even wait until 10 times. For cases
607             // where we see non-index-intercepting objects, this gives 10 iterations worth of
608             // opportunity for us to observe that the get_by_val may be polymorphic.
609             if (++byValInfo.slowPathCount >= 10
610                 || object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
611                 // Don't ever try to optimize.
612                 ctiPatchCallByReturnAddress(callFrame->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationDirectPutByValGeneric));
613             }
614         }
615     }
616     directPutByVal(callFrame, object, subscript, value);
617 }
618
619 void JIT_OPERATION operationPutByValGeneric(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
620 {
621     VM& vm = exec->vm();
622     NativeCallFrameTracer tracer(&vm, exec);
623     
624     JSValue baseValue = JSValue::decode(encodedBaseValue);
625     JSValue subscript = JSValue::decode(encodedSubscript);
626     JSValue value = JSValue::decode(encodedValue);
627
628     putByVal(exec, baseValue, subscript, value);
629 }
630
631
632 void JIT_OPERATION operationDirectPutByValGeneric(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
633 {
634     VM& vm = exec->vm();
635     NativeCallFrameTracer tracer(&vm, exec);
636     
637     JSValue baseValue = JSValue::decode(encodedBaseValue);
638     JSValue subscript = JSValue::decode(encodedSubscript);
639     JSValue value = JSValue::decode(encodedValue);
640     RELEASE_ASSERT(baseValue.isObject());
641     directPutByVal(exec, asObject(baseValue), subscript, value);
642 }
643
644 EncodedJSValue JIT_OPERATION operationCallEval(ExecState* exec, ExecState* execCallee)
645 {
646
647     ASSERT_UNUSED(exec, exec->codeBlock()->codeType() != FunctionCode
648         || !exec->codeBlock()->needsActivation()
649         || exec->hasActivation());
650
651     execCallee->setCodeBlock(0);
652
653     if (!isHostFunction(execCallee->calleeAsValue(), globalFuncEval))
654         return JSValue::encode(JSValue());
655
656     VM* vm = &execCallee->vm();
657     JSValue result = eval(execCallee);
658     if (vm->exception())
659         return EncodedJSValue();
660     
661     return JSValue::encode(result);
662 }
663
664 static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializationKind kind)
665 {
666     ExecState* exec = execCallee->callerFrame();
667     VM* vm = &exec->vm();
668
669     execCallee->setCodeBlock(0);
670
671     if (kind == CodeForCall) {
672         CallData callData;
673         CallType callType = getCallData(callee, callData);
674     
675         ASSERT(callType != CallTypeJS);
676     
677         if (callType == CallTypeHost) {
678             NativeCallFrameTracer tracer(vm, execCallee);
679             execCallee->setCallee(asObject(callee));
680             vm->hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
681             if (vm->exception())
682                 return vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
683
684             return reinterpret_cast<void*>(getHostCallReturnValue);
685         }
686     
687         ASSERT(callType == CallTypeNone);
688         exec->vm().throwException(exec, createNotAFunctionError(exec, callee));
689         return vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
690     }
691
692     ASSERT(kind == CodeForConstruct);
693     
694     ConstructData constructData;
695     ConstructType constructType = getConstructData(callee, constructData);
696     
697     ASSERT(constructType != ConstructTypeJS);
698     
699     if (constructType == ConstructTypeHost) {
700         NativeCallFrameTracer tracer(vm, execCallee);
701         execCallee->setCallee(asObject(callee));
702         vm->hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee));
703         if (vm->exception())
704             return vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
705
706         return reinterpret_cast<void*>(getHostCallReturnValue);
707     }
708     
709     ASSERT(constructType == ConstructTypeNone);
710     exec->vm().throwException(exec, createNotAConstructorError(exec, callee));
711     return vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
712 }
713
714 inline char* linkFor(
715     ExecState* execCallee, CallLinkInfo* callLinkInfo, CodeSpecializationKind kind,
716     RegisterPreservationMode registers)
717 {
718     ExecState* exec = execCallee->callerFrame();
719     VM* vm = &exec->vm();
720     NativeCallFrameTracer tracer(vm, exec);
721     
722     JSValue calleeAsValue = execCallee->calleeAsValue();
723     JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
724     if (!calleeAsFunctionCell)
725         return reinterpret_cast<char*>(handleHostCall(execCallee, calleeAsValue, kind));
726
727     JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell);
728     JSScope* scope = callee->scopeUnchecked();
729     ExecutableBase* executable = callee->executable();
730
731     MacroAssemblerCodePtr codePtr;
732     CodeBlock* codeBlock = 0;
733     if (executable->isHostFunction())
734         codePtr = executable->entrypointFor(*vm, kind, MustCheckArity, registers);
735     else {
736         FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
737         JSObject* error = functionExecutable->prepareForExecution(execCallee, callee, scope, kind);
738         if (error) {
739             throwStackOverflowError(exec);
740             return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
741         }
742         codeBlock = functionExecutable->codeBlockFor(kind);
743         ArityCheckMode arity;
744         if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo->callType == CallLinkInfo::CallVarargs || callLinkInfo->callType == CallLinkInfo::ConstructVarargs)
745             arity = MustCheckArity;
746         else
747             arity = ArityCheckNotRequired;
748         codePtr = functionExecutable->entrypointFor(*vm, kind, arity, registers);
749     }
750     if (!callLinkInfo->seenOnce())
751         callLinkInfo->setSeen();
752     else
753         linkFor(execCallee, *callLinkInfo, codeBlock, callee, codePtr, kind, registers);
754     
755     return reinterpret_cast<char*>(codePtr.executableAddress());
756 }
757
758 char* JIT_OPERATION operationLinkCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
759 {
760     return linkFor(execCallee, callLinkInfo, CodeForCall, RegisterPreservationNotRequired);
761 }
762
763 char* JIT_OPERATION operationLinkConstruct(ExecState* execCallee, CallLinkInfo* callLinkInfo)
764 {
765     return linkFor(execCallee, callLinkInfo, CodeForConstruct, RegisterPreservationNotRequired);
766 }
767
768 char* JIT_OPERATION operationLinkCallThatPreservesRegs(ExecState* execCallee, CallLinkInfo* callLinkInfo)
769 {
770     return linkFor(execCallee, callLinkInfo, CodeForCall, MustPreserveRegisters);
771 }
772
773 char* JIT_OPERATION operationLinkConstructThatPreservesRegs(ExecState* execCallee, CallLinkInfo* callLinkInfo)
774 {
775     return linkFor(execCallee, callLinkInfo, CodeForConstruct, MustPreserveRegisters);
776 }
777
778 inline char* virtualForWithFunction(
779     ExecState* execCallee, CodeSpecializationKind kind, RegisterPreservationMode registers,
780     JSCell*& calleeAsFunctionCell)
781 {
782     ExecState* exec = execCallee->callerFrame();
783     VM* vm = &exec->vm();
784     NativeCallFrameTracer tracer(vm, exec);
785
786     JSValue calleeAsValue = execCallee->calleeAsValue();
787     calleeAsFunctionCell = getJSFunction(calleeAsValue);
788     if (UNLIKELY(!calleeAsFunctionCell))
789         return reinterpret_cast<char*>(handleHostCall(execCallee, calleeAsValue, kind));
790     
791     JSFunction* function = jsCast<JSFunction*>(calleeAsFunctionCell);
792     JSScope* scope = function->scopeUnchecked();
793     ExecutableBase* executable = function->executable();
794     if (UNLIKELY(!executable->hasJITCodeFor(kind))) {
795         FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
796         JSObject* error = functionExecutable->prepareForExecution(execCallee, function, scope, kind);
797         if (error) {
798             exec->vm().throwException(exec, error);
799             return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
800         }
801     }
802     return reinterpret_cast<char*>(executable->entrypointFor(
803         *vm, kind, MustCheckArity, registers).executableAddress());
804 }
805
806 inline char* virtualFor(
807     ExecState* execCallee, CodeSpecializationKind kind, RegisterPreservationMode registers)
808 {
809     JSCell* calleeAsFunctionCellIgnored;
810     return virtualForWithFunction(execCallee, kind, registers, calleeAsFunctionCellIgnored);
811 }
812
813 char* JIT_OPERATION operationLinkPolymorphicCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
814 {
815     JSCell* calleeAsFunctionCell;
816     char* result = virtualForWithFunction(execCallee, CodeForCall, RegisterPreservationNotRequired, calleeAsFunctionCell);
817
818     linkPolymorphicCall(execCallee, *callLinkInfo, CallVariant(calleeAsFunctionCell), RegisterPreservationNotRequired);
819     
820     return result;
821 }
822
823 char* JIT_OPERATION operationVirtualCall(ExecState* execCallee, CallLinkInfo*)
824 {    
825     return virtualFor(execCallee, CodeForCall, RegisterPreservationNotRequired);
826 }
827
828 char* JIT_OPERATION operationVirtualConstruct(ExecState* execCallee, CallLinkInfo*)
829 {
830     return virtualFor(execCallee, CodeForConstruct, RegisterPreservationNotRequired);
831 }
832
833 char* JIT_OPERATION operationLinkPolymorphicCallThatPreservesRegs(ExecState* execCallee, CallLinkInfo* callLinkInfo)
834 {
835     JSCell* calleeAsFunctionCell;
836     char* result = virtualForWithFunction(execCallee, CodeForCall, MustPreserveRegisters, calleeAsFunctionCell);
837
838     linkPolymorphicCall(execCallee, *callLinkInfo, CallVariant(calleeAsFunctionCell), MustPreserveRegisters);
839     
840     return result;
841 }
842
843 char* JIT_OPERATION operationVirtualCallThatPreservesRegs(ExecState* execCallee, CallLinkInfo*)
844 {    
845     return virtualFor(execCallee, CodeForCall, MustPreserveRegisters);
846 }
847
848 char* JIT_OPERATION operationVirtualConstructThatPreservesRegs(ExecState* execCallee, CallLinkInfo*)
849 {
850     return virtualFor(execCallee, CodeForConstruct, MustPreserveRegisters);
851 }
852
853 size_t JIT_OPERATION operationCompareLess(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
854 {
855     VM* vm = &exec->vm();
856     NativeCallFrameTracer tracer(vm, exec);
857     
858     return jsLess<true>(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
859 }
860
861 size_t JIT_OPERATION operationCompareLessEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
862 {
863     VM* vm = &exec->vm();
864     NativeCallFrameTracer tracer(vm, exec);
865
866     return jsLessEq<true>(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
867 }
868
869 size_t JIT_OPERATION operationCompareGreater(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
870 {
871     VM* vm = &exec->vm();
872     NativeCallFrameTracer tracer(vm, exec);
873
874     return jsLess<false>(exec, JSValue::decode(encodedOp2), JSValue::decode(encodedOp1));
875 }
876
877 size_t JIT_OPERATION operationCompareGreaterEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
878 {
879     VM* vm = &exec->vm();
880     NativeCallFrameTracer tracer(vm, exec);
881
882     return jsLessEq<false>(exec, JSValue::decode(encodedOp2), JSValue::decode(encodedOp1));
883 }
884
885 size_t JIT_OPERATION operationConvertJSValueToBoolean(ExecState* exec, EncodedJSValue encodedOp)
886 {
887     VM* vm = &exec->vm();
888     NativeCallFrameTracer tracer(vm, exec);
889     
890     return JSValue::decode(encodedOp).toBoolean(exec);
891 }
892
893 size_t JIT_OPERATION operationCompareEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
894 {
895     VM* vm = &exec->vm();
896     NativeCallFrameTracer tracer(vm, exec);
897
898     return JSValue::equalSlowCaseInline(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
899 }
900
901 #if USE(JSVALUE64)
902 EncodedJSValue JIT_OPERATION operationCompareStringEq(ExecState* exec, JSCell* left, JSCell* right)
903 #else
904 size_t JIT_OPERATION operationCompareStringEq(ExecState* exec, JSCell* left, JSCell* right)
905 #endif
906 {
907     VM* vm = &exec->vm();
908     NativeCallFrameTracer tracer(vm, exec);
909
910     bool result = WTF::equal(*asString(left)->value(exec).impl(), *asString(right)->value(exec).impl());
911 #if USE(JSVALUE64)
912     return JSValue::encode(jsBoolean(result));
913 #else
914     return result;
915 #endif
916 }
917
918 size_t JIT_OPERATION operationHasProperty(ExecState* exec, JSObject* base, JSString* property)
919 {
920     int result = base->hasProperty(exec, property->toIdentifier(exec));
921     return result;
922 }
923     
924
925 EncodedJSValue JIT_OPERATION operationNewArrayWithProfile(ExecState* exec, ArrayAllocationProfile* profile, const JSValue* values, int size)
926 {
927     VM* vm = &exec->vm();
928     NativeCallFrameTracer tracer(vm, exec);
929     return JSValue::encode(constructArrayNegativeIndexed(exec, profile, values, size));
930 }
931
932 EncodedJSValue JIT_OPERATION operationNewArrayBufferWithProfile(ExecState* exec, ArrayAllocationProfile* profile, const JSValue* values, int size)
933 {
934     VM* vm = &exec->vm();
935     NativeCallFrameTracer tracer(vm, exec);
936     return JSValue::encode(constructArray(exec, profile, values, size));
937 }
938
939 EncodedJSValue JIT_OPERATION operationNewArrayWithSizeAndProfile(ExecState* exec, ArrayAllocationProfile* profile, EncodedJSValue size)
940 {
941     VM* vm = &exec->vm();
942     NativeCallFrameTracer tracer(vm, exec);
943     JSValue sizeValue = JSValue::decode(size);
944     return JSValue::encode(constructArrayWithSizeQuirk(exec, profile, exec->lexicalGlobalObject(), sizeValue));
945 }
946
947 EncodedJSValue JIT_OPERATION operationNewFunction(ExecState* exec, JSScope* scope, JSCell* functionExecutable)
948 {
949     ASSERT(functionExecutable->inherits(FunctionExecutable::info()));
950     VM& vm = exec->vm();
951     NativeCallFrameTracer tracer(&vm, exec);
952     return JSValue::encode(JSFunction::create(vm, static_cast<FunctionExecutable*>(functionExecutable), scope));
953 }
954
955 EncodedJSValue JIT_OPERATION operationNewFunctionWithInvalidatedReallocationWatchpoint(ExecState* exec, JSScope* scope, JSCell* functionExecutable)
956 {
957     ASSERT(functionExecutable->inherits(FunctionExecutable::info()));
958     VM& vm = exec->vm();
959     NativeCallFrameTracer tracer(&vm, exec);
960     return JSValue::encode(JSFunction::createWithInvalidatedReallocationWatchpoint(vm, static_cast<FunctionExecutable*>(functionExecutable), scope));
961 }
962
963 JSCell* JIT_OPERATION operationNewObject(ExecState* exec, Structure* structure)
964 {
965     VM* vm = &exec->vm();
966     NativeCallFrameTracer tracer(vm, exec);
967     
968     return constructEmptyObject(exec, structure);
969 }
970
971 EncodedJSValue JIT_OPERATION operationNewRegexp(ExecState* exec, void* regexpPtr)
972 {
973     VM& vm = exec->vm();
974     NativeCallFrameTracer tracer(&vm, exec);
975     RegExp* regexp = static_cast<RegExp*>(regexpPtr);
976     if (!regexp->isValid()) {
977         vm.throwException(exec, createSyntaxError(exec, ASCIILiteral("Invalid flags supplied to RegExp constructor.")));
978         return JSValue::encode(jsUndefined());
979     }
980
981     return JSValue::encode(RegExpObject::create(vm, exec->lexicalGlobalObject()->regExpStructure(), regexp));
982 }
983
984 void JIT_OPERATION operationHandleWatchdogTimer(ExecState* exec)
985 {
986     VM& vm = exec->vm();
987     NativeCallFrameTracer tracer(&vm, exec);
988
989     if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(exec)))
990         vm.throwException(exec, createTerminatedExecutionException(&vm));
991 }
992
993 void JIT_OPERATION operationThrowStaticError(ExecState* exec, EncodedJSValue encodedValue, int32_t referenceErrorFlag)
994 {
995     VM& vm = exec->vm();
996     NativeCallFrameTracer tracer(&vm, exec);
997     JSValue errorMessageValue = JSValue::decode(encodedValue);
998     RELEASE_ASSERT(errorMessageValue.isString());
999     String errorMessage = asString(errorMessageValue)->value(exec);
1000     if (referenceErrorFlag)
1001         vm.throwException(exec, createReferenceError(exec, errorMessage));
1002     else
1003         vm.throwException(exec, createTypeError(exec, errorMessage));
1004 }
1005
1006 void JIT_OPERATION operationDebug(ExecState* exec, int32_t debugHookID)
1007 {
1008     VM& vm = exec->vm();
1009     NativeCallFrameTracer tracer(&vm, exec);
1010
1011     vm.interpreter->debug(exec, static_cast<DebugHookID>(debugHookID));
1012 }
1013
1014 #if ENABLE(DFG_JIT)
1015 static void updateAllPredictionsAndOptimizeAfterWarmUp(CodeBlock* codeBlock)
1016 {
1017     codeBlock->updateAllPredictions();
1018     codeBlock->optimizeAfterWarmUp();
1019 }
1020
1021 SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t bytecodeIndex)
1022 {
1023     VM& vm = exec->vm();
1024     NativeCallFrameTracer tracer(&vm, exec);
1025
1026     // Defer GC for a while so that it doesn't run between when we enter into this
1027     // slow path and when we figure out the state of our code block. This prevents
1028     // a number of awkward reentrancy scenarios, including:
1029     //
1030     // - The optimized version of our code block being jettisoned by GC right after
1031     //   we concluded that we wanted to use it, but have not planted it into the JS
1032     //   stack yet.
1033     //
1034     // - An optimized version of our code block being installed just as we decided
1035     //   that it wasn't ready yet.
1036     //
1037     // Note that jettisoning won't happen if we already initiated OSR, because in
1038     // that case we would have already planted the optimized code block into the JS
1039     // stack.
1040     DeferGCForAWhile deferGC(vm.heap);
1041     
1042     CodeBlock* codeBlock = exec->codeBlock();
1043     if (codeBlock->jitType() != JITCode::BaselineJIT) {
1044         dataLog("Unexpected code block in Baseline->DFG tier-up: ", *codeBlock, "\n");
1045         RELEASE_ASSERT_NOT_REACHED();
1046     }
1047     
1048     if (bytecodeIndex) {
1049         // If we're attempting to OSR from a loop, assume that this should be
1050         // separately optimized.
1051         codeBlock->m_shouldAlwaysBeInlined = false;
1052     }
1053
1054     if (Options::verboseOSR()) {
1055         dataLog(
1056             *codeBlock, ": Entered optimize with bytecodeIndex = ", bytecodeIndex,
1057             ", executeCounter = ", codeBlock->jitExecuteCounter(),
1058             ", optimizationDelayCounter = ", codeBlock->reoptimizationRetryCounter(),
1059             ", exitCounter = ");
1060         if (codeBlock->hasOptimizedReplacement())
1061             dataLog(codeBlock->replacement()->osrExitCounter());
1062         else
1063             dataLog("N/A");
1064         dataLog("\n");
1065     }
1066
1067     if (!codeBlock->checkIfOptimizationThresholdReached()) {
1068         codeBlock->updateAllPredictions();
1069         if (Options::verboseOSR())
1070             dataLog("Choosing not to optimize ", *codeBlock, " yet, because the threshold hasn't been reached.\n");
1071         return encodeResult(0, 0);
1072     }
1073     
1074     if (vm.enabledProfiler()) {
1075         updateAllPredictionsAndOptimizeAfterWarmUp(codeBlock);
1076         return encodeResult(0, 0);
1077     }
1078
1079     Debugger* debugger = codeBlock->globalObject()->debugger();
1080     if (debugger && (debugger->isStepping() || codeBlock->baselineAlternative()->hasDebuggerRequests())) {
1081         updateAllPredictionsAndOptimizeAfterWarmUp(codeBlock);
1082         return encodeResult(0, 0);
1083     }
1084
1085     if (codeBlock->m_shouldAlwaysBeInlined) {
1086         updateAllPredictionsAndOptimizeAfterWarmUp(codeBlock);
1087         if (Options::verboseOSR())
1088             dataLog("Choosing not to optimize ", *codeBlock, " yet, because m_shouldAlwaysBeInlined == true.\n");
1089         return encodeResult(0, 0);
1090     }
1091
1092     // We cannot be in the process of asynchronous compilation and also have an optimized
1093     // replacement.
1094     DFG::Worklist* worklist = DFG::existingGlobalDFGWorklistOrNull();
1095     ASSERT(
1096         !worklist
1097         || !(worklist->compilationState(DFG::CompilationKey(codeBlock, DFG::DFGMode)) != DFG::Worklist::NotKnown
1098         && codeBlock->hasOptimizedReplacement()));
1099
1100     DFG::Worklist::State worklistState;
1101     if (worklist) {
1102         // The call to DFG::Worklist::completeAllReadyPlansForVM() will complete all ready
1103         // (i.e. compiled) code blocks. But if it completes ours, we also need to know
1104         // what the result was so that we don't plow ahead and attempt OSR or immediate
1105         // reoptimization. This will have already also set the appropriate JIT execution
1106         // count threshold depending on what happened, so if the compilation was anything
1107         // but successful we just want to return early. See the case for worklistState ==
1108         // DFG::Worklist::Compiled, below.
1109         
1110         // Note that we could have alternatively just called Worklist::compilationState()
1111         // here, and if it returned Compiled, we could have then called
1112         // completeAndScheduleOSR() below. But that would have meant that it could take
1113         // longer for code blocks to be completed: they would only complete when *their*
1114         // execution count trigger fired; but that could take a while since the firing is
1115         // racy. It could also mean that code blocks that never run again after being
1116         // compiled would sit on the worklist until next GC. That's fine, but it's
1117         // probably a waste of memory. Our goal here is to complete code blocks as soon as
1118         // possible in order to minimize the chances of us executing baseline code after
1119         // optimized code is already available.
1120         worklistState = worklist->completeAllReadyPlansForVM(
1121             vm, DFG::CompilationKey(codeBlock, DFG::DFGMode));
1122     } else
1123         worklistState = DFG::Worklist::NotKnown;
1124
1125     if (worklistState == DFG::Worklist::Compiling) {
1126         // We cannot be in the process of asynchronous compilation and also have an optimized
1127         // replacement.
1128         RELEASE_ASSERT(!codeBlock->hasOptimizedReplacement());
1129         codeBlock->setOptimizationThresholdBasedOnCompilationResult(CompilationDeferred);
1130         return encodeResult(0, 0);
1131     }
1132
1133     if (worklistState == DFG::Worklist::Compiled) {
1134         // If we don't have an optimized replacement but we did just get compiled, then
1135         // the compilation failed or was invalidated, in which case the execution count
1136         // thresholds have already been set appropriately by
1137         // CodeBlock::setOptimizationThresholdBasedOnCompilationResult() and we have
1138         // nothing left to do.
1139         if (!codeBlock->hasOptimizedReplacement()) {
1140             codeBlock->updateAllPredictions();
1141             if (Options::verboseOSR())
1142                 dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
1143             return encodeResult(0, 0);
1144         }
1145     } else if (codeBlock->hasOptimizedReplacement()) {
1146         if (Options::verboseOSR())
1147             dataLog("Considering OSR ", *codeBlock, " -> ", *codeBlock->replacement(), ".\n");
1148         // If we have an optimized replacement, then it must be the case that we entered
1149         // cti_optimize from a loop. That's because if there's an optimized replacement,
1150         // then all calls to this function will be relinked to the replacement and so
1151         // the prologue OSR will never fire.
1152         
1153         // This is an interesting threshold check. Consider that a function OSR exits
1154         // in the middle of a loop, while having a relatively low exit count. The exit
1155         // will reset the execution counter to some target threshold, meaning that this
1156         // code won't be reached until that loop heats up for >=1000 executions. But then
1157         // we do a second check here, to see if we should either reoptimize, or just
1158         // attempt OSR entry. Hence it might even be correct for
1159         // shouldReoptimizeFromLoopNow() to always return true. But we make it do some
1160         // additional checking anyway, to reduce the amount of recompilation thrashing.
1161         if (codeBlock->replacement()->shouldReoptimizeFromLoopNow()) {
1162             if (Options::verboseOSR()) {
1163                 dataLog(
1164                     "Triggering reoptimization of ", *codeBlock,
1165                     "(", *codeBlock->replacement(), ") (in loop).\n");
1166             }
1167             codeBlock->replacement()->jettison(Profiler::JettisonDueToBaselineLoopReoptimizationTrigger, CountReoptimization);
1168             return encodeResult(0, 0);
1169         }
1170     } else {
1171         if (!codeBlock->shouldOptimizeNow()) {
1172             if (Options::verboseOSR()) {
1173                 dataLog(
1174                     "Delaying optimization for ", *codeBlock,
1175                     " because of insufficient profiling.\n");
1176             }
1177             return encodeResult(0, 0);
1178         }
1179
1180         if (Options::verboseOSR())
1181             dataLog("Triggering optimized compilation of ", *codeBlock, "\n");
1182
1183         unsigned numVarsWithValues;
1184         if (bytecodeIndex)
1185             numVarsWithValues = codeBlock->m_numVars;
1186         else
1187             numVarsWithValues = 0;
1188         Operands<JSValue> mustHandleValues(codeBlock->numParameters(), numVarsWithValues);
1189         for (size_t i = 0; i < mustHandleValues.size(); ++i) {
1190             int operand = mustHandleValues.operandForIndex(i);
1191             mustHandleValues[i] = exec->uncheckedR(operand).jsValue();
1192         }
1193
1194         RefPtr<CodeBlock> replacementCodeBlock = codeBlock->newReplacement();
1195         CompilationResult result = DFG::compile(
1196             vm, replacementCodeBlock.get(), 0, DFG::DFGMode, bytecodeIndex,
1197             mustHandleValues, JITToDFGDeferredCompilationCallback::create());
1198         
1199         if (result != CompilationSuccessful) {
1200             ASSERT(result == CompilationDeferred || replacementCodeBlock->hasOneRef());
1201             return encodeResult(0, 0);
1202         }
1203     }
1204     
1205     CodeBlock* optimizedCodeBlock = codeBlock->replacement();
1206     ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
1207     
1208     if (void* dataBuffer = DFG::prepareOSREntry(exec, optimizedCodeBlock, bytecodeIndex)) {
1209         if (Options::verboseOSR()) {
1210             dataLog(
1211                 "Performing OSR ", *codeBlock, " -> ", *optimizedCodeBlock, ".\n");
1212         }
1213
1214         codeBlock->optimizeSoon();
1215         return encodeResult(vm.getCTIStub(DFG::osrEntryThunkGenerator).code().executableAddress(), dataBuffer);
1216     }
1217
1218     if (Options::verboseOSR()) {
1219         dataLog(
1220             "Optimizing ", *codeBlock, " -> ", *codeBlock->replacement(),
1221             " succeeded, OSR failed, after a delay of ",
1222             codeBlock->optimizationDelayCounter(), ".\n");
1223     }
1224
1225     // Count the OSR failure as a speculation failure. If this happens a lot, then
1226     // reoptimize.
1227     optimizedCodeBlock->countOSRExit();
1228
1229     // We are a lot more conservative about triggering reoptimization after OSR failure than
1230     // before it. If we enter the optimize_from_loop trigger with a bucket full of fail
1231     // already, then we really would like to reoptimize immediately. But this case covers
1232     // something else: there weren't many (or any) speculation failures before, but we just
1233     // failed to enter the speculative code because some variable had the wrong value or
1234     // because the OSR code decided for any spurious reason that it did not want to OSR
1235     // right now. So, we only trigger reoptimization only upon the more conservative (non-loop)
1236     // reoptimization trigger.
1237     if (optimizedCodeBlock->shouldReoptimizeNow()) {
1238         if (Options::verboseOSR()) {
1239             dataLog(
1240                 "Triggering reoptimization of ", *codeBlock, " -> ",
1241                 *codeBlock->replacement(), " (after OSR fail).\n");
1242         }
1243         optimizedCodeBlock->jettison(Profiler::JettisonDueToBaselineLoopReoptimizationTriggerOnOSREntryFail, CountReoptimization);
1244         return encodeResult(0, 0);
1245     }
1246
1247     // OSR failed this time, but it might succeed next time! Let the code run a bit
1248     // longer and then try again.
1249     codeBlock->optimizeAfterWarmUp();
1250     
1251     return encodeResult(0, 0);
1252 }
1253 #endif
1254
1255 void JIT_OPERATION operationPutByIndex(ExecState* exec, EncodedJSValue encodedArrayValue, int32_t index, EncodedJSValue encodedValue)
1256 {
1257     VM& vm = exec->vm();
1258     NativeCallFrameTracer tracer(&vm, exec);
1259
1260     JSValue arrayValue = JSValue::decode(encodedArrayValue);
1261     ASSERT(isJSArray(arrayValue));
1262     asArray(arrayValue)->putDirectIndex(exec, index, JSValue::decode(encodedValue));
1263 }
1264
1265 #if USE(JSVALUE64)
1266 void JIT_OPERATION operationPutGetterSetter(ExecState* exec, EncodedJSValue encodedObjectValue, Identifier* identifier, EncodedJSValue encodedGetterValue, EncodedJSValue encodedSetterValue)
1267 {
1268     VM& vm = exec->vm();
1269     NativeCallFrameTracer tracer(&vm, exec);
1270
1271     ASSERT(JSValue::decode(encodedObjectValue).isObject());
1272     JSObject* baseObj = asObject(JSValue::decode(encodedObjectValue));
1273
1274     GetterSetter* accessor = GetterSetter::create(vm, exec->lexicalGlobalObject());
1275
1276     JSValue getter = JSValue::decode(encodedGetterValue);
1277     JSValue setter = JSValue::decode(encodedSetterValue);
1278     ASSERT(getter.isObject() || getter.isUndefined());
1279     ASSERT(setter.isObject() || setter.isUndefined());
1280     ASSERT(getter.isObject() || setter.isObject());
1281
1282     if (!getter.isUndefined())
1283         accessor->setGetter(vm, exec->lexicalGlobalObject(), asObject(getter));
1284     if (!setter.isUndefined())
1285         accessor->setSetter(vm, exec->lexicalGlobalObject(), asObject(setter));
1286     baseObj->putDirectAccessor(exec, *identifier, accessor, Accessor);
1287 }
1288 #else
1289 void JIT_OPERATION operationPutGetterSetter(ExecState* exec, JSCell* object, Identifier* identifier, JSCell* getter, JSCell* setter)
1290 {
1291     VM& vm = exec->vm();
1292     NativeCallFrameTracer tracer(&vm, exec);
1293
1294     ASSERT(object && object->isObject());
1295     JSObject* baseObj = object->getObject();
1296
1297     GetterSetter* accessor = GetterSetter::create(vm, exec->lexicalGlobalObject());
1298
1299     ASSERT(!getter || getter->isObject());
1300     ASSERT(!setter || setter->isObject());
1301     ASSERT(getter || setter);
1302
1303     if (getter)
1304         accessor->setGetter(vm, exec->lexicalGlobalObject(), getter->getObject());
1305     if (setter)
1306         accessor->setSetter(vm, exec->lexicalGlobalObject(), setter->getObject());
1307     baseObj->putDirectAccessor(exec, *identifier, accessor, Accessor);
1308 }
1309 #endif
1310
1311 void JIT_OPERATION operationPushCatchScope(ExecState* exec, int32_t dst, SymbolTable* symbolTable, EncodedJSValue encodedValue)
1312 {
1313     pushNameScope<JSCatchScope>(exec, dst, symbolTable, encodedValue);
1314 }
1315
1316 void JIT_OPERATION operationPushFunctionNameScope(ExecState* exec, int32_t dst, SymbolTable* symbolTable, EncodedJSValue encodedValue)
1317 {
1318     pushNameScope<JSFunctionNameScope>(exec, dst, symbolTable, encodedValue);
1319 }
1320
1321 void JIT_OPERATION operationPushWithScope(ExecState* exec, int32_t dst, EncodedJSValue encodedValue)
1322 {
1323     VM& vm = exec->vm();
1324     NativeCallFrameTracer tracer(&vm, exec);
1325
1326     JSObject* o = JSValue::decode(encodedValue).toObject(exec);
1327     if (vm.exception())
1328         return;
1329
1330     // FIXME: This won't work if this operation is called from the DFG or FTL.
1331     // This should be changed to pass in the old scope and return the new scope.
1332     JSScope* currentScope = exec->uncheckedR(dst).Register::scope();
1333     exec->uncheckedR(dst) = JSWithScope::create(exec, o, currentScope);
1334 }
1335
1336 void JIT_OPERATION operationPopScope(ExecState* exec, int32_t scopeReg)
1337 {
1338     VM& vm = exec->vm();
1339     NativeCallFrameTracer tracer(&vm, exec);
1340
1341     JSScope* scope = exec->uncheckedR(scopeReg).Register::scope();
1342     exec->uncheckedR(scopeReg) = scope->next();
1343 }
1344
1345 void JIT_OPERATION operationProfileDidCall(ExecState* exec, EncodedJSValue encodedValue)
1346 {
1347     VM& vm = exec->vm();
1348     NativeCallFrameTracer tracer(&vm, exec);
1349
1350     if (LegacyProfiler* profiler = vm.enabledProfiler())
1351         profiler->didExecute(exec, JSValue::decode(encodedValue));
1352 }
1353
1354 void JIT_OPERATION operationProfileWillCall(ExecState* exec, EncodedJSValue encodedValue)
1355 {
1356     VM& vm = exec->vm();
1357     NativeCallFrameTracer tracer(&vm, exec);
1358
1359     if (LegacyProfiler* profiler = vm.enabledProfiler())
1360         profiler->willExecute(exec, JSValue::decode(encodedValue));
1361 }
1362
1363 EncodedJSValue JIT_OPERATION operationCheckHasInstance(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBaseVal)
1364 {
1365     VM& vm = exec->vm();
1366     NativeCallFrameTracer tracer(&vm, exec);
1367
1368     JSValue value = JSValue::decode(encodedValue);
1369     JSValue baseVal = JSValue::decode(encodedBaseVal);
1370
1371     if (baseVal.isObject()) {
1372         JSObject* baseObject = asObject(baseVal);
1373         ASSERT(!baseObject->structure(vm)->typeInfo().implementsDefaultHasInstance());
1374         if (baseObject->structure(vm)->typeInfo().implementsHasInstance()) {
1375             bool result = baseObject->methodTable(vm)->customHasInstance(baseObject, exec, value);
1376             return JSValue::encode(jsBoolean(result));
1377         }
1378     }
1379
1380     vm.throwException(exec, createInvalidInstanceofParameterError(exec, baseVal));
1381     return JSValue::encode(JSValue());
1382 }
1383
1384 JSCell* JIT_OPERATION operationCreateActivation(ExecState* exec, JSScope* currentScope)
1385 {
1386     VM& vm = exec->vm();
1387     NativeCallFrameTracer tracer(&vm, exec);
1388     JSLexicalEnvironment* lexicalEnvironment = JSLexicalEnvironment::create(vm, exec, currentScope, exec->codeBlock());
1389     return lexicalEnvironment;
1390 }
1391
1392 }
1393
1394 static JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript, ReturnAddressPtr returnAddress)
1395 {
1396     if (LIKELY(baseValue.isCell() && subscript.isString())) {
1397         VM& vm = exec->vm();
1398         Structure& structure = *baseValue.asCell()->structure(vm);
1399         if (JSCell::canUseFastGetOwnProperty(structure)) {
1400             if (AtomicStringImpl* existingAtomicString = asString(subscript)->toExistingAtomicString(exec)) {
1401                 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString))
1402                     return result;
1403             }
1404         }
1405     }
1406
1407     if (subscript.isUInt32()) {
1408         uint32_t i = subscript.asUInt32();
1409         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) {
1410             ctiPatchCallByReturnAddress(exec->codeBlock(), returnAddress, FunctionPtr(operationGetByValString));
1411             return asString(baseValue)->getIndex(exec, i);
1412         }
1413         return baseValue.get(exec, i);
1414     }
1415
1416     baseValue.requireObjectCoercible(exec);
1417     if (exec->hadException())
1418         return jsUndefined();
1419     auto property = subscript.toPropertyKey(exec);
1420     if (exec->hadException())
1421         return jsUndefined();
1422     return baseValue.get(exec, property);
1423 }
1424
1425 extern "C" {
1426     
1427 EncodedJSValue JIT_OPERATION operationGetByValGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
1428 {
1429     VM& vm = exec->vm();
1430     NativeCallFrameTracer tracer(&vm, exec);
1431     JSValue baseValue = JSValue::decode(encodedBase);
1432     JSValue subscript = JSValue::decode(encodedSubscript);
1433
1434     JSValue result = getByVal(exec, baseValue, subscript, ReturnAddressPtr(OUR_RETURN_ADDRESS));
1435     return JSValue::encode(result);
1436 }
1437
1438 EncodedJSValue JIT_OPERATION operationGetByValDefault(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
1439 {
1440     VM& vm = exec->vm();
1441     NativeCallFrameTracer tracer(&vm, exec);
1442     JSValue baseValue = JSValue::decode(encodedBase);
1443     JSValue subscript = JSValue::decode(encodedSubscript);
1444     
1445     if (baseValue.isObject() && subscript.isInt32()) {
1446         // See if it's worth optimizing this at all.
1447         JSObject* object = asObject(baseValue);
1448         bool didOptimize = false;
1449
1450         unsigned bytecodeOffset = exec->locationAsBytecodeOffset();
1451         ASSERT(bytecodeOffset);
1452         ByValInfo& byValInfo = exec->codeBlock()->getByValInfo(bytecodeOffset - 1);
1453         ASSERT(!byValInfo.stubRoutine);
1454         
1455         if (hasOptimizableIndexing(object->structure(vm))) {
1456             // Attempt to optimize.
1457             JITArrayMode arrayMode = jitArrayModeForStructure(object->structure(vm));
1458             if (arrayMode != byValInfo.arrayMode) {
1459                 JIT::compileGetByVal(&vm, exec->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
1460                 didOptimize = true;
1461             }
1462         }
1463         
1464         if (!didOptimize) {
1465             // If we take slow path more than 10 times without patching then make sure we
1466             // never make that mistake again. Or, if we failed to patch and we have some object
1467             // that intercepts indexed get, then don't even wait until 10 times. For cases
1468             // where we see non-index-intercepting objects, this gives 10 iterations worth of
1469             // opportunity for us to observe that the get_by_val may be polymorphic.
1470             if (++byValInfo.slowPathCount >= 10
1471                 || object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
1472                 // Don't ever try to optimize.
1473                 ctiPatchCallByReturnAddress(exec->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationGetByValGeneric));
1474             }
1475         }
1476     }
1477     
1478     JSValue result = getByVal(exec, baseValue, subscript, ReturnAddressPtr(OUR_RETURN_ADDRESS));
1479     return JSValue::encode(result);
1480 }
1481     
1482 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyDefault(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
1483 {
1484     VM& vm = exec->vm();
1485     NativeCallFrameTracer tracer(&vm, exec);
1486     JSValue baseValue = JSValue::decode(encodedBase);
1487     JSValue subscript = JSValue::decode(encodedSubscript);
1488     
1489     ASSERT(baseValue.isObject());
1490     ASSERT(subscript.isUInt32());
1491
1492     JSObject* object = asObject(baseValue);
1493     bool didOptimize = false;
1494
1495     unsigned bytecodeOffset = exec->locationAsBytecodeOffset();
1496     ASSERT(bytecodeOffset);
1497     ByValInfo& byValInfo = exec->codeBlock()->getByValInfo(bytecodeOffset - 1);
1498     ASSERT(!byValInfo.stubRoutine);
1499     
1500     if (hasOptimizableIndexing(object->structure(vm))) {
1501         // Attempt to optimize.
1502         JITArrayMode arrayMode = jitArrayModeForStructure(object->structure(vm));
1503         if (arrayMode != byValInfo.arrayMode) {
1504             JIT::compileHasIndexedProperty(&vm, exec->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
1505             didOptimize = true;
1506         }
1507     }
1508     
1509     if (!didOptimize) {
1510         // If we take slow path more than 10 times without patching then make sure we
1511         // never make that mistake again. Or, if we failed to patch and we have some object
1512         // that intercepts indexed get, then don't even wait until 10 times. For cases
1513         // where we see non-index-intercepting objects, this gives 10 iterations worth of
1514         // opportunity for us to observe that the get_by_val may be polymorphic.
1515         if (++byValInfo.slowPathCount >= 10
1516             || object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
1517             // Don't ever try to optimize.
1518             ctiPatchCallByReturnAddress(exec->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationHasIndexedPropertyGeneric)); 
1519         }
1520     }
1521     
1522     return JSValue::encode(jsBoolean(object->hasProperty(exec, subscript.asUInt32())));
1523 }
1524     
1525 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
1526 {
1527     VM& vm = exec->vm();
1528     NativeCallFrameTracer tracer(&vm, exec);
1529     JSValue baseValue = JSValue::decode(encodedBase);
1530     JSValue subscript = JSValue::decode(encodedSubscript);
1531     
1532     ASSERT(baseValue.isObject());
1533     ASSERT(subscript.isUInt32());
1534
1535     JSObject* object = asObject(baseValue);
1536     return JSValue::encode(jsBoolean(object->hasProperty(exec, subscript.asUInt32())));
1537 }
1538     
1539 EncodedJSValue JIT_OPERATION operationGetByValString(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
1540 {
1541     VM& vm = exec->vm();
1542     NativeCallFrameTracer tracer(&vm, exec);
1543     JSValue baseValue = JSValue::decode(encodedBase);
1544     JSValue subscript = JSValue::decode(encodedSubscript);
1545     
1546     JSValue result;
1547     if (LIKELY(subscript.isUInt32())) {
1548         uint32_t i = subscript.asUInt32();
1549         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
1550             result = asString(baseValue)->getIndex(exec, i);
1551         else {
1552             result = baseValue.get(exec, i);
1553             if (!isJSString(baseValue))
1554                 ctiPatchCallByReturnAddress(exec->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationGetByValDefault));
1555         }
1556     } else {
1557         baseValue.requireObjectCoercible(exec);
1558         if (exec->hadException())
1559             return JSValue::encode(jsUndefined());
1560         auto property = subscript.toPropertyKey(exec);
1561         if (exec->hadException())
1562             return JSValue::encode(jsUndefined());
1563         result = baseValue.get(exec, property);
1564     }
1565
1566     return JSValue::encode(result);
1567 }
1568
1569 EncodedJSValue JIT_OPERATION operationDeleteById(ExecState* exec, EncodedJSValue encodedBase, const Identifier* identifier)
1570 {
1571     VM& vm = exec->vm();
1572     NativeCallFrameTracer tracer(&vm, exec);
1573
1574     JSObject* baseObj = JSValue::decode(encodedBase).toObject(exec);
1575     bool couldDelete = baseObj->methodTable(vm)->deleteProperty(baseObj, exec, *identifier);
1576     JSValue result = jsBoolean(couldDelete);
1577     if (!couldDelete && exec->codeBlock()->isStrictMode())
1578         vm.throwException(exec, createTypeError(exec, ASCIILiteral("Unable to delete property.")));
1579     return JSValue::encode(result);
1580 }
1581
1582 EncodedJSValue JIT_OPERATION operationInstanceOf(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedProto)
1583 {
1584     VM& vm = exec->vm();
1585     NativeCallFrameTracer tracer(&vm, exec);
1586     JSValue value = JSValue::decode(encodedValue);
1587     JSValue proto = JSValue::decode(encodedProto);
1588     
1589     ASSERT(!value.isObject() || !proto.isObject());
1590
1591     bool result = JSObject::defaultHasInstance(exec, value, proto);
1592     return JSValue::encode(jsBoolean(result));
1593 }
1594
1595 int32_t JIT_OPERATION operationSizeFrameForVarargs(ExecState* exec, EncodedJSValue encodedArguments, int32_t numUsedStackSlots, int32_t firstVarArgOffset)
1596 {
1597     VM& vm = exec->vm();
1598     NativeCallFrameTracer tracer(&vm, exec);
1599     JSStack* stack = &exec->interpreter()->stack();
1600     JSValue arguments = JSValue::decode(encodedArguments);
1601     return sizeFrameForVarargs(exec, stack, arguments, numUsedStackSlots, firstVarArgOffset);
1602 }
1603
1604 CallFrame* JIT_OPERATION operationSetupVarargsFrame(ExecState* exec, CallFrame* newCallFrame, EncodedJSValue encodedArguments, int32_t firstVarArgOffset, int32_t length)
1605 {
1606     VM& vm = exec->vm();
1607     NativeCallFrameTracer tracer(&vm, exec);
1608     JSValue arguments = JSValue::decode(encodedArguments);
1609     setupVarargsFrame(exec, newCallFrame, arguments, firstVarArgOffset, length);
1610     return newCallFrame;
1611 }
1612
1613 EncodedJSValue JIT_OPERATION operationToObject(ExecState* exec, EncodedJSValue value)
1614 {
1615     VM& vm = exec->vm();
1616     NativeCallFrameTracer tracer(&vm, exec);
1617     return JSValue::encode(JSValue::decode(value).toObject(exec));
1618 }
1619
1620 char* JIT_OPERATION operationSwitchCharWithUnknownKeyType(ExecState* exec, EncodedJSValue encodedKey, size_t tableIndex)
1621 {
1622     VM& vm = exec->vm();
1623     NativeCallFrameTracer tracer(&vm, exec);
1624     JSValue key = JSValue::decode(encodedKey);
1625     CodeBlock* codeBlock = exec->codeBlock();
1626
1627     SimpleJumpTable& jumpTable = codeBlock->switchJumpTable(tableIndex);
1628     void* result = jumpTable.ctiDefault.executableAddress();
1629
1630     if (key.isString()) {
1631         StringImpl* value = asString(key)->value(exec).impl();
1632         if (value->length() == 1)
1633             result = jumpTable.ctiForValue((*value)[0]).executableAddress();
1634     }
1635
1636     return reinterpret_cast<char*>(result);
1637 }
1638
1639 char* JIT_OPERATION operationSwitchImmWithUnknownKeyType(ExecState* exec, EncodedJSValue encodedKey, size_t tableIndex)
1640 {
1641     VM& vm = exec->vm();
1642     NativeCallFrameTracer tracer(&vm, exec);
1643     JSValue key = JSValue::decode(encodedKey);
1644     CodeBlock* codeBlock = exec->codeBlock();
1645
1646     SimpleJumpTable& jumpTable = codeBlock->switchJumpTable(tableIndex);
1647     void* result;
1648     if (key.isInt32())
1649         result = jumpTable.ctiForValue(key.asInt32()).executableAddress();
1650     else if (key.isDouble() && key.asDouble() == static_cast<int32_t>(key.asDouble()))
1651         result = jumpTable.ctiForValue(static_cast<int32_t>(key.asDouble())).executableAddress();
1652     else
1653         result = jumpTable.ctiDefault.executableAddress();
1654     return reinterpret_cast<char*>(result);
1655 }
1656
1657 char* JIT_OPERATION operationSwitchStringWithUnknownKeyType(ExecState* exec, EncodedJSValue encodedKey, size_t tableIndex)
1658 {
1659     VM& vm = exec->vm();
1660     NativeCallFrameTracer tracer(&vm, exec);
1661     JSValue key = JSValue::decode(encodedKey);
1662     CodeBlock* codeBlock = exec->codeBlock();
1663
1664     void* result;
1665     StringJumpTable& jumpTable = codeBlock->stringSwitchJumpTable(tableIndex);
1666
1667     if (key.isString()) {
1668         StringImpl* value = asString(key)->value(exec).impl();
1669         result = jumpTable.ctiForValue(value).executableAddress();
1670     } else
1671         result = jumpTable.ctiDefault.executableAddress();
1672
1673     return reinterpret_cast<char*>(result);
1674 }
1675
1676 EncodedJSValue JIT_OPERATION operationResolveScope(ExecState* exec, int32_t scopeReg, int32_t identifierIndex)
1677 {
1678     VM& vm = exec->vm();
1679     NativeCallFrameTracer tracer(&vm, exec);
1680     const Identifier& ident = exec->codeBlock()->identifier(identifierIndex);
1681     JSScope* scope = exec->uncheckedR(scopeReg).Register::scope();
1682     return JSValue::encode(JSScope::resolve(exec, scope, ident));
1683 }
1684
1685 EncodedJSValue JIT_OPERATION operationGetFromScope(ExecState* exec, Instruction* bytecodePC)
1686 {
1687     VM& vm = exec->vm();
1688     NativeCallFrameTracer tracer(&vm, exec);
1689     CodeBlock* codeBlock = exec->codeBlock();
1690     Instruction* pc = bytecodePC;
1691
1692     const Identifier& ident = codeBlock->identifier(pc[3].u.operand);
1693     JSObject* scope = jsCast<JSObject*>(exec->uncheckedR(pc[2].u.operand).jsValue());
1694     ResolveModeAndType modeAndType(pc[4].u.operand);
1695
1696     PropertySlot slot(scope);
1697     if (!scope->getPropertySlot(exec, ident, slot)) {
1698         if (modeAndType.mode() == ThrowIfNotFound)
1699             vm.throwException(exec, createUndefinedVariableError(exec, ident));
1700         return JSValue::encode(jsUndefined());
1701     }
1702
1703     // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time.
1704     if (slot.isCacheableValue() && slot.slotBase() == scope && scope->structure(vm)->propertyAccessesAreCacheable()) {
1705         if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) {
1706             Structure* structure = scope->structure(vm);
1707             {
1708                 ConcurrentJITLocker locker(codeBlock->m_lock);
1709                 pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), structure);
1710                 pc[6].u.operand = slot.cachedOffset();
1711             }
1712             structure->startWatchingPropertyForReplacements(vm, slot.cachedOffset());
1713         }
1714     }
1715
1716     return JSValue::encode(slot.getValue(exec, ident));
1717 }
1718
1719 void JIT_OPERATION operationPutToScope(ExecState* exec, Instruction* bytecodePC)
1720 {
1721     VM& vm = exec->vm();
1722     NativeCallFrameTracer tracer(&vm, exec);
1723     Instruction* pc = bytecodePC;
1724
1725     CodeBlock* codeBlock = exec->codeBlock();
1726     const Identifier& ident = codeBlock->identifier(pc[2].u.operand);
1727     JSObject* scope = jsCast<JSObject*>(exec->uncheckedR(pc[1].u.operand).jsValue());
1728     JSValue value = exec->r(pc[3].u.operand).jsValue();
1729     ResolveModeAndType modeAndType = ResolveModeAndType(pc[4].u.operand);
1730     if (modeAndType.type() == LocalClosureVar) {
1731         JSLexicalEnvironment* environment = jsCast<JSLexicalEnvironment*>(scope);
1732         environment->variableAt(ScopeOffset(pc[6].u.operand)).set(vm, environment, value);
1733         if (WatchpointSet* set = pc[5].u.watchpointSet)
1734             set->touch("Executed op_put_scope<LocalClosureVar>");
1735         return;
1736     }
1737     if (modeAndType.mode() == ThrowIfNotFound && !scope->hasProperty(exec, ident)) {
1738         exec->vm().throwException(exec, createUndefinedVariableError(exec, ident));
1739         return;
1740     }
1741
1742     PutPropertySlot slot(scope, codeBlock->isStrictMode());
1743     scope->methodTable()->put(scope, exec, ident, value, slot);
1744     
1745     if (exec->vm().exception())
1746         return;
1747
1748     CommonSlowPaths::tryCachePutToScopeGlobal(exec, codeBlock, pc, scope, modeAndType, slot);
1749 }
1750
1751 void JIT_OPERATION operationThrow(ExecState* exec, EncodedJSValue encodedExceptionValue)
1752 {
1753     VM* vm = &exec->vm();
1754     NativeCallFrameTracer tracer(vm, exec);
1755
1756     JSValue exceptionValue = JSValue::decode(encodedExceptionValue);
1757     vm->throwException(exec, exceptionValue);
1758
1759     // Results stored out-of-band in vm.targetMachinePCForThrow, vm.callFrameForThrow & vm.vmEntryFrameForThrow
1760     genericUnwind(vm, exec, exceptionValue);
1761 }
1762
1763 void JIT_OPERATION operationFlushWriteBarrierBuffer(ExecState* exec, JSCell* cell)
1764 {
1765     VM* vm = &exec->vm();
1766     NativeCallFrameTracer tracer(vm, exec);
1767     vm->heap.flushWriteBarrierBuffer(cell);
1768 }
1769
1770 void JIT_OPERATION operationOSRWriteBarrier(ExecState* exec, JSCell* cell)
1771 {
1772     VM* vm = &exec->vm();
1773     NativeCallFrameTracer tracer(vm, exec);
1774     vm->heap.writeBarrier(cell);
1775 }
1776
1777 // NB: We don't include the value as part of the barrier because the write barrier elision
1778 // phase in the DFG only tracks whether the object being stored to has been barriered. It 
1779 // would be much more complicated to try to model the value being stored as well.
1780 void JIT_OPERATION operationUnconditionalWriteBarrier(ExecState* exec, JSCell* cell)
1781 {
1782     VM* vm = &exec->vm();
1783     NativeCallFrameTracer tracer(vm, exec);
1784     vm->heap.writeBarrier(cell);
1785 }
1786
1787 void JIT_OPERATION operationInitGlobalConst(ExecState* exec, Instruction* pc)
1788 {
1789     VM* vm = &exec->vm();
1790     NativeCallFrameTracer tracer(vm, exec);
1791
1792     JSValue value = exec->r(pc[2].u.operand).jsValue();
1793     pc[1].u.variablePointer->set(*vm, exec->codeBlock()->globalObject(), value);
1794 }
1795
1796 void JIT_OPERATION lookupExceptionHandler(VM* vm, ExecState* exec)
1797 {
1798     NativeCallFrameTracer tracer(vm, exec);
1799
1800     JSValue exceptionValue = vm->exception();
1801     ASSERT(exceptionValue);
1802     
1803     genericUnwind(vm, exec, exceptionValue);
1804     ASSERT(vm->targetMachinePCForThrow);
1805 }
1806
1807 void JIT_OPERATION lookupExceptionHandlerFromCallerFrame(VM* vm, ExecState* exec)
1808 {
1809     VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
1810     CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
1811     ASSERT(callerFrame);
1812
1813     NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
1814
1815     JSValue exceptionValue = vm->exception();
1816     ASSERT(exceptionValue);
1817     
1818     genericUnwind(vm, callerFrame, exceptionValue);
1819     ASSERT(vm->targetMachinePCForThrow);
1820 }
1821
1822 void JIT_OPERATION operationVMHandleException(ExecState* exec)
1823 {
1824     VM* vm = &exec->vm();
1825     NativeCallFrameTracer tracer(vm, exec);
1826
1827     genericUnwind(vm, exec, vm->exception());
1828 }
1829
1830 // This function "should" just take the ExecState*, but doing so would make it more difficult
1831 // to call from exception check sites. So, unlike all of our other functions, we allow
1832 // ourselves to play some gnarly ABI tricks just to simplify the calling convention. This is
1833 // particularly safe here since this is never called on the critical path - it's only for
1834 // testing.
1835 void JIT_OPERATION operationExceptionFuzz()
1836 {
1837     // This probably "just works" for GCC also, but I haven't tried.
1838 #if COMPILER(CLANG)
1839     ExecState* exec = static_cast<ExecState*>(__builtin_frame_address(1));
1840     void* returnPC = __builtin_return_address(0);
1841     doExceptionFuzzing(exec, "JITOperations", returnPC);
1842 #endif // COMPILER(CLANG)
1843 }
1844
1845 EncodedJSValue JIT_OPERATION operationHasGenericProperty(ExecState* exec, EncodedJSValue encodedBaseValue, JSCell* propertyName)
1846 {
1847     VM& vm = exec->vm();
1848     NativeCallFrameTracer tracer(&vm, exec);
1849     JSValue baseValue = JSValue::decode(encodedBaseValue);
1850     if (baseValue.isUndefinedOrNull())
1851         return JSValue::encode(jsBoolean(false));
1852
1853     JSObject* base = baseValue.toObject(exec);
1854     return JSValue::encode(jsBoolean(base->hasProperty(exec, asString(propertyName)->toIdentifier(exec))));
1855 }
1856
1857 EncodedJSValue JIT_OPERATION operationHasIndexedProperty(ExecState* exec, JSCell* baseCell, int32_t subscript)
1858 {
1859     VM& vm = exec->vm();
1860     NativeCallFrameTracer tracer(&vm, exec);
1861     JSObject* object = baseCell->toObject(exec, exec->lexicalGlobalObject());
1862     return JSValue::encode(jsBoolean(object->hasProperty(exec, subscript)));
1863 }
1864     
1865 JSCell* JIT_OPERATION operationGetPropertyEnumerator(ExecState* exec, JSCell* cell)
1866 {
1867     VM& vm = exec->vm();
1868     NativeCallFrameTracer tracer(&vm, exec);
1869
1870     JSObject* base = cell->toObject(exec, exec->lexicalGlobalObject());
1871
1872     return propertyNameEnumerator(exec, base);
1873 }
1874
1875 EncodedJSValue JIT_OPERATION operationNextEnumeratorPname(ExecState* exec, JSCell* enumeratorCell, int32_t index)
1876 {
1877     VM& vm = exec->vm();
1878     NativeCallFrameTracer tracer(&vm, exec);
1879     JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(enumeratorCell);
1880     JSString* propertyName = enumerator->propertyNameAtIndex(index);
1881     return JSValue::encode(propertyName ? propertyName : jsNull());
1882 }
1883
1884 JSCell* JIT_OPERATION operationToIndexString(ExecState* exec, int32_t index)
1885 {
1886     VM& vm = exec->vm();
1887     NativeCallFrameTracer tracer(&vm, exec);
1888     return jsString(exec, Identifier::from(exec, index).string());
1889 }
1890
1891 void JIT_OPERATION operationProcessTypeProfilerLog(ExecState* exec)
1892 {
1893     exec->vm().typeProfilerLog()->processLogEntries(ASCIILiteral("Log Full, called from inside baseline JIT"));
1894 }
1895
1896 } // extern "C"
1897
1898 // Note: getHostCallReturnValueWithExecState() needs to be placed before the
1899 // definition of getHostCallReturnValue() below because the Windows build
1900 // requires it.
1901 extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValueWithExecState(ExecState* exec)
1902 {
1903     if (!exec)
1904         return JSValue::encode(JSValue());
1905     return JSValue::encode(exec->vm().hostCallReturnValue);
1906 }
1907
1908 #if COMPILER(GCC) && CPU(X86_64)
1909 asm (
1910 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1911 HIDE_SYMBOL(getHostCallReturnValue) "\n"
1912 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
1913     "mov %rbp, %rdi\n"
1914     "jmp " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
1915 );
1916
1917 #elif COMPILER(GCC) && CPU(X86)
1918 asm (
1919 ".text" "\n" \
1920 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1921 HIDE_SYMBOL(getHostCallReturnValue) "\n"
1922 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
1923     "push %ebp\n"
1924     "leal -4(%esp), %esp\n"
1925     "push %ebp\n"
1926     "call " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
1927     "leal 8(%esp), %esp\n"
1928     "pop %ebp\n"
1929     "ret\n"
1930 );
1931
1932 #elif COMPILER(GCC) && CPU(ARM_THUMB2)
1933 asm (
1934 ".text" "\n"
1935 ".align 2" "\n"
1936 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1937 HIDE_SYMBOL(getHostCallReturnValue) "\n"
1938 ".thumb" "\n"
1939 ".thumb_func " THUMB_FUNC_PARAM(getHostCallReturnValue) "\n"
1940 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
1941     "mov r0, r7" "\n"
1942     "b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
1943 );
1944
1945 #elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
1946 asm (
1947 ".text" "\n"
1948 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1949 HIDE_SYMBOL(getHostCallReturnValue) "\n"
1950 INLINE_ARM_FUNCTION(getHostCallReturnValue)
1951 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
1952     "mov r0, r11" "\n"
1953     "b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
1954 );
1955
1956 #elif CPU(ARM64)
1957 asm (
1958 ".text" "\n"
1959 ".align 2" "\n"
1960 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1961 HIDE_SYMBOL(getHostCallReturnValue) "\n"
1962 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
1963      "mov x0, x29" "\n"
1964      "b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
1965 );
1966
1967 #elif COMPILER(GCC) && CPU(MIPS)
1968
1969 #if WTF_MIPS_PIC
1970 #define LOAD_FUNCTION_TO_T9(function) \
1971         ".set noreorder" "\n" \
1972         ".cpload $25" "\n" \
1973         ".set reorder" "\n" \
1974         "la $t9, " LOCAL_REFERENCE(function) "\n"
1975 #else
1976 #define LOAD_FUNCTION_TO_T9(function) "" "\n"
1977 #endif
1978
1979 asm (
1980 ".text" "\n"
1981 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1982 HIDE_SYMBOL(getHostCallReturnValue) "\n"
1983 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
1984     LOAD_FUNCTION_TO_T9(getHostCallReturnValueWithExecState)
1985     "move $a0, $fp" "\n"
1986     "b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
1987 );
1988
1989 #elif COMPILER(GCC) && CPU(SH4)
1990
1991 #define SH4_SCRATCH_REGISTER "r11"
1992
1993 asm (
1994 ".text" "\n"
1995 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1996 HIDE_SYMBOL(getHostCallReturnValue) "\n"
1997 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
1998     "mov r14, r4" "\n"
1999     "mov.l 2f, " SH4_SCRATCH_REGISTER "\n"
2000     "braf " SH4_SCRATCH_REGISTER "\n"
2001     "nop" "\n"
2002     "1: .balign 4" "\n"
2003     "2: .long " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "-1b\n"
2004 );
2005
2006 #elif COMPILER(MSVC) && CPU(X86)
2007 extern "C" {
2008     __declspec(naked) EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValue()
2009     {
2010         __asm mov [esp + 4], ebp;
2011         __asm jmp getHostCallReturnValueWithExecState
2012     }
2013 }
2014 #endif
2015
2016 } // namespace JSC
2017
2018 #endif // ENABLE(JIT)