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