Implement ES6 Symbol
[WebKit-https.git] / Source / JavaScriptCore / jit / JITOperations.cpp
1 /*
2  * Copyright (C) 2013, 2014 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 static bool attemptToOptimizeClosureCall(
774     ExecState* execCallee, RegisterPreservationMode registers, JSCell* calleeAsFunctionCell,
775     CallLinkInfo& callLinkInfo)
776 {
777     if (!calleeAsFunctionCell)
778         return false;
779     
780     JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell);
781     JSFunction* oldCallee = callLinkInfo.callee.get();
782     
783     if (!oldCallee || oldCallee->executable() != callee->executable())
784         return false;
785     
786     ASSERT(callee->executable()->hasJITCodeForCall());
787     MacroAssemblerCodePtr codePtr =
788         callee->executable()->generatedJITCodeForCall()->addressForCall(
789             *execCallee->callerFrame()->codeBlock()->vm(), callee->executable(),
790             ArityCheckNotRequired, registers);
791     
792     CodeBlock* codeBlock;
793     if (callee->executable()->isHostFunction())
794         codeBlock = 0;
795     else {
796         codeBlock = jsCast<FunctionExecutable*>(callee->executable())->codeBlockForCall();
797         if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo.callType == CallLinkInfo::CallVarargs || callLinkInfo.callType == CallLinkInfo::ConstructVarargs)
798             return false;
799     }
800     
801     linkClosureCall(
802         execCallee, callLinkInfo, codeBlock, callee->executable(), codePtr, registers);
803     
804     return true;
805 }
806
807 char* JIT_OPERATION operationLinkClosureCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
808 {
809     JSCell* calleeAsFunctionCell;
810     char* result = virtualForWithFunction(execCallee, CodeForCall, RegisterPreservationNotRequired, calleeAsFunctionCell);
811
812     if (!attemptToOptimizeClosureCall(execCallee, RegisterPreservationNotRequired, calleeAsFunctionCell, *callLinkInfo))
813         linkSlowFor(execCallee, *callLinkInfo, CodeForCall, RegisterPreservationNotRequired);
814     
815     return result;
816 }
817
818 char* JIT_OPERATION operationVirtualCall(ExecState* execCallee, CallLinkInfo*)
819 {    
820     return virtualFor(execCallee, CodeForCall, RegisterPreservationNotRequired);
821 }
822
823 char* JIT_OPERATION operationVirtualConstruct(ExecState* execCallee, CallLinkInfo*)
824 {
825     return virtualFor(execCallee, CodeForConstruct, RegisterPreservationNotRequired);
826 }
827
828 char* JIT_OPERATION operationLinkClosureCallThatPreservesRegs(ExecState* execCallee, CallLinkInfo* callLinkInfo)
829 {
830     JSCell* calleeAsFunctionCell;
831     char* result = virtualForWithFunction(execCallee, CodeForCall, MustPreserveRegisters, calleeAsFunctionCell);
832
833     if (!attemptToOptimizeClosureCall(execCallee, MustPreserveRegisters, calleeAsFunctionCell, *callLinkInfo))
834         linkSlowFor(execCallee, *callLinkInfo, CodeForCall, MustPreserveRegisters);
835     
836     return result;
837 }
838
839 char* JIT_OPERATION operationVirtualCallThatPreservesRegs(ExecState* execCallee, CallLinkInfo*)
840 {    
841     return virtualFor(execCallee, CodeForCall, MustPreserveRegisters);
842 }
843
844 char* JIT_OPERATION operationVirtualConstructThatPreservesRegs(ExecState* execCallee, CallLinkInfo*)
845 {
846     return virtualFor(execCallee, CodeForConstruct, MustPreserveRegisters);
847 }
848
849 size_t JIT_OPERATION operationCompareLess(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
850 {
851     VM* vm = &exec->vm();
852     NativeCallFrameTracer tracer(vm, exec);
853     
854     return jsLess<true>(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
855 }
856
857 size_t JIT_OPERATION operationCompareLessEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
858 {
859     VM* vm = &exec->vm();
860     NativeCallFrameTracer tracer(vm, exec);
861
862     return jsLessEq<true>(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
863 }
864
865 size_t JIT_OPERATION operationCompareGreater(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
866 {
867     VM* vm = &exec->vm();
868     NativeCallFrameTracer tracer(vm, exec);
869
870     return jsLess<false>(exec, JSValue::decode(encodedOp2), JSValue::decode(encodedOp1));
871 }
872
873 size_t JIT_OPERATION operationCompareGreaterEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
874 {
875     VM* vm = &exec->vm();
876     NativeCallFrameTracer tracer(vm, exec);
877
878     return jsLessEq<false>(exec, JSValue::decode(encodedOp2), JSValue::decode(encodedOp1));
879 }
880
881 size_t JIT_OPERATION operationConvertJSValueToBoolean(ExecState* exec, EncodedJSValue encodedOp)
882 {
883     VM* vm = &exec->vm();
884     NativeCallFrameTracer tracer(vm, exec);
885     
886     return JSValue::decode(encodedOp).toBoolean(exec);
887 }
888
889 size_t JIT_OPERATION operationCompareEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
890 {
891     VM* vm = &exec->vm();
892     NativeCallFrameTracer tracer(vm, exec);
893
894     return JSValue::equalSlowCaseInline(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
895 }
896
897 #if USE(JSVALUE64)
898 EncodedJSValue JIT_OPERATION operationCompareStringEq(ExecState* exec, JSCell* left, JSCell* right)
899 #else
900 size_t JIT_OPERATION operationCompareStringEq(ExecState* exec, JSCell* left, JSCell* right)
901 #endif
902 {
903     VM* vm = &exec->vm();
904     NativeCallFrameTracer tracer(vm, exec);
905
906     bool result = WTF::equal(*asString(left)->value(exec).impl(), *asString(right)->value(exec).impl());
907 #if USE(JSVALUE64)
908     return JSValue::encode(jsBoolean(result));
909 #else
910     return result;
911 #endif
912 }
913
914 size_t JIT_OPERATION operationHasProperty(ExecState* exec, JSObject* base, JSString* property)
915 {
916     int result = base->hasProperty(exec, property->toIdentifier(exec));
917     return result;
918 }
919     
920
921 EncodedJSValue JIT_OPERATION operationNewArrayWithProfile(ExecState* exec, ArrayAllocationProfile* profile, const JSValue* values, int size)
922 {
923     VM* vm = &exec->vm();
924     NativeCallFrameTracer tracer(vm, exec);
925     return JSValue::encode(constructArrayNegativeIndexed(exec, profile, values, size));
926 }
927
928 EncodedJSValue JIT_OPERATION operationNewArrayBufferWithProfile(ExecState* exec, ArrayAllocationProfile* profile, const JSValue* values, int size)
929 {
930     VM* vm = &exec->vm();
931     NativeCallFrameTracer tracer(vm, exec);
932     return JSValue::encode(constructArray(exec, profile, values, size));
933 }
934
935 EncodedJSValue JIT_OPERATION operationNewArrayWithSizeAndProfile(ExecState* exec, ArrayAllocationProfile* profile, EncodedJSValue size)
936 {
937     VM* vm = &exec->vm();
938     NativeCallFrameTracer tracer(vm, exec);
939     JSValue sizeValue = JSValue::decode(size);
940     return JSValue::encode(constructArrayWithSizeQuirk(exec, profile, exec->lexicalGlobalObject(), sizeValue));
941 }
942
943 EncodedJSValue JIT_OPERATION operationNewFunction(ExecState* exec, JSScope* scope, JSCell* functionExecutable)
944 {
945     ASSERT(functionExecutable->inherits(FunctionExecutable::info()));
946     VM& vm = exec->vm();
947     NativeCallFrameTracer tracer(&vm, exec);
948     return JSValue::encode(JSFunction::create(vm, static_cast<FunctionExecutable*>(functionExecutable), scope));
949 }
950
951 JSCell* JIT_OPERATION operationNewObject(ExecState* exec, Structure* structure)
952 {
953     VM* vm = &exec->vm();
954     NativeCallFrameTracer tracer(vm, exec);
955     
956     return constructEmptyObject(exec, structure);
957 }
958
959 EncodedJSValue JIT_OPERATION operationNewRegexp(ExecState* exec, void* regexpPtr)
960 {
961     VM& vm = exec->vm();
962     NativeCallFrameTracer tracer(&vm, exec);
963     RegExp* regexp = static_cast<RegExp*>(regexpPtr);
964     if (!regexp->isValid()) {
965         vm.throwException(exec, createSyntaxError(exec, ASCIILiteral("Invalid flags supplied to RegExp constructor.")));
966         return JSValue::encode(jsUndefined());
967     }
968
969     return JSValue::encode(RegExpObject::create(vm, exec->lexicalGlobalObject()->regExpStructure(), regexp));
970 }
971
972 void JIT_OPERATION operationHandleWatchdogTimer(ExecState* exec)
973 {
974     VM& vm = exec->vm();
975     NativeCallFrameTracer tracer(&vm, exec);
976
977     if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(exec)))
978         vm.throwException(exec, createTerminatedExecutionException(&vm));
979 }
980
981 void JIT_OPERATION operationThrowStaticError(ExecState* exec, EncodedJSValue encodedValue, int32_t referenceErrorFlag)
982 {
983     VM& vm = exec->vm();
984     NativeCallFrameTracer tracer(&vm, exec);
985
986     String message = errorDescriptionForValue(exec, JSValue::decode(encodedValue))->value(exec);
987     if (referenceErrorFlag)
988         vm.throwException(exec, createReferenceError(exec, message));
989     else
990         vm.throwException(exec, createTypeError(exec, message));
991 }
992
993 void JIT_OPERATION operationDebug(ExecState* exec, int32_t debugHookID)
994 {
995     VM& vm = exec->vm();
996     NativeCallFrameTracer tracer(&vm, exec);
997
998     vm.interpreter->debug(exec, static_cast<DebugHookID>(debugHookID));
999 }
1000
1001 #if ENABLE(DFG_JIT)
1002 static void updateAllPredictionsAndOptimizeAfterWarmUp(CodeBlock* codeBlock)
1003 {
1004     codeBlock->updateAllPredictions();
1005     codeBlock->optimizeAfterWarmUp();
1006 }
1007
1008 SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t bytecodeIndex)
1009 {
1010     VM& vm = exec->vm();
1011     NativeCallFrameTracer tracer(&vm, exec);
1012
1013     // Defer GC for a while so that it doesn't run between when we enter into this
1014     // slow path and when we figure out the state of our code block. This prevents
1015     // a number of awkward reentrancy scenarios, including:
1016     //
1017     // - The optimized version of our code block being jettisoned by GC right after
1018     //   we concluded that we wanted to use it, but have not planted it into the JS
1019     //   stack yet.
1020     //
1021     // - An optimized version of our code block being installed just as we decided
1022     //   that it wasn't ready yet.
1023     //
1024     // Note that jettisoning won't happen if we already initiated OSR, because in
1025     // that case we would have already planted the optimized code block into the JS
1026     // stack.
1027     DeferGCForAWhile deferGC(vm.heap);
1028     
1029     CodeBlock* codeBlock = exec->codeBlock();
1030     
1031     if (bytecodeIndex) {
1032         // If we're attempting to OSR from a loop, assume that this should be
1033         // separately optimized.
1034         codeBlock->m_shouldAlwaysBeInlined = false;
1035     }
1036
1037     if (Options::verboseOSR()) {
1038         dataLog(
1039             *codeBlock, ": Entered optimize with bytecodeIndex = ", bytecodeIndex,
1040             ", executeCounter = ", codeBlock->jitExecuteCounter(),
1041             ", optimizationDelayCounter = ", codeBlock->reoptimizationRetryCounter(),
1042             ", exitCounter = ");
1043         if (codeBlock->hasOptimizedReplacement())
1044             dataLog(codeBlock->replacement()->osrExitCounter());
1045         else
1046             dataLog("N/A");
1047         dataLog("\n");
1048     }
1049
1050     if (!codeBlock->checkIfOptimizationThresholdReached()) {
1051         codeBlock->updateAllPredictions();
1052         if (Options::verboseOSR())
1053             dataLog("Choosing not to optimize ", *codeBlock, " yet, because the threshold hasn't been reached.\n");
1054         return encodeResult(0, 0);
1055     }
1056     
1057     if (vm.enabledProfiler()) {
1058         updateAllPredictionsAndOptimizeAfterWarmUp(codeBlock);
1059         return encodeResult(0, 0);
1060     }
1061
1062     Debugger* debugger = codeBlock->globalObject()->debugger();
1063     if (debugger && (debugger->isStepping() || codeBlock->baselineAlternative()->hasDebuggerRequests())) {
1064         updateAllPredictionsAndOptimizeAfterWarmUp(codeBlock);
1065         return encodeResult(0, 0);
1066     }
1067
1068     if (codeBlock->m_shouldAlwaysBeInlined) {
1069         updateAllPredictionsAndOptimizeAfterWarmUp(codeBlock);
1070         if (Options::verboseOSR())
1071             dataLog("Choosing not to optimize ", *codeBlock, " yet, because m_shouldAlwaysBeInlined == true.\n");
1072         return encodeResult(0, 0);
1073     }
1074
1075     // We cannot be in the process of asynchronous compilation and also have an optimized
1076     // replacement.
1077     DFG::Worklist* worklist = DFG::existingGlobalDFGWorklistOrNull();
1078     ASSERT(
1079         !worklist
1080         || !(worklist->compilationState(DFG::CompilationKey(codeBlock, DFG::DFGMode)) != DFG::Worklist::NotKnown
1081         && codeBlock->hasOptimizedReplacement()));
1082
1083     DFG::Worklist::State worklistState;
1084     if (worklist) {
1085         // The call to DFG::Worklist::completeAllReadyPlansForVM() will complete all ready
1086         // (i.e. compiled) code blocks. But if it completes ours, we also need to know
1087         // what the result was so that we don't plow ahead and attempt OSR or immediate
1088         // reoptimization. This will have already also set the appropriate JIT execution
1089         // count threshold depending on what happened, so if the compilation was anything
1090         // but successful we just want to return early. See the case for worklistState ==
1091         // DFG::Worklist::Compiled, below.
1092         
1093         // Note that we could have alternatively just called Worklist::compilationState()
1094         // here, and if it returned Compiled, we could have then called
1095         // completeAndScheduleOSR() below. But that would have meant that it could take
1096         // longer for code blocks to be completed: they would only complete when *their*
1097         // execution count trigger fired; but that could take a while since the firing is
1098         // racy. It could also mean that code blocks that never run again after being
1099         // compiled would sit on the worklist until next GC. That's fine, but it's
1100         // probably a waste of memory. Our goal here is to complete code blocks as soon as
1101         // possible in order to minimize the chances of us executing baseline code after
1102         // optimized code is already available.
1103         worklistState = worklist->completeAllReadyPlansForVM(
1104             vm, DFG::CompilationKey(codeBlock, DFG::DFGMode));
1105     } else
1106         worklistState = DFG::Worklist::NotKnown;
1107
1108     if (worklistState == DFG::Worklist::Compiling) {
1109         // We cannot be in the process of asynchronous compilation and also have an optimized
1110         // replacement.
1111         RELEASE_ASSERT(!codeBlock->hasOptimizedReplacement());
1112         codeBlock->setOptimizationThresholdBasedOnCompilationResult(CompilationDeferred);
1113         return encodeResult(0, 0);
1114     }
1115
1116     if (worklistState == DFG::Worklist::Compiled) {
1117         // If we don't have an optimized replacement but we did just get compiled, then
1118         // the compilation failed or was invalidated, in which case the execution count
1119         // thresholds have already been set appropriately by
1120         // CodeBlock::setOptimizationThresholdBasedOnCompilationResult() and we have
1121         // nothing left to do.
1122         if (!codeBlock->hasOptimizedReplacement()) {
1123             codeBlock->updateAllPredictions();
1124             if (Options::verboseOSR())
1125                 dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
1126             return encodeResult(0, 0);
1127         }
1128     } else if (codeBlock->hasOptimizedReplacement()) {
1129         if (Options::verboseOSR())
1130             dataLog("Considering OSR ", *codeBlock, " -> ", *codeBlock->replacement(), ".\n");
1131         // If we have an optimized replacement, then it must be the case that we entered
1132         // cti_optimize from a loop. That's because if there's an optimized replacement,
1133         // then all calls to this function will be relinked to the replacement and so
1134         // the prologue OSR will never fire.
1135         
1136         // This is an interesting threshold check. Consider that a function OSR exits
1137         // in the middle of a loop, while having a relatively low exit count. The exit
1138         // will reset the execution counter to some target threshold, meaning that this
1139         // code won't be reached until that loop heats up for >=1000 executions. But then
1140         // we do a second check here, to see if we should either reoptimize, or just
1141         // attempt OSR entry. Hence it might even be correct for
1142         // shouldReoptimizeFromLoopNow() to always return true. But we make it do some
1143         // additional checking anyway, to reduce the amount of recompilation thrashing.
1144         if (codeBlock->replacement()->shouldReoptimizeFromLoopNow()) {
1145             if (Options::verboseOSR()) {
1146                 dataLog(
1147                     "Triggering reoptimization of ", *codeBlock,
1148                     "(", *codeBlock->replacement(), ") (in loop).\n");
1149             }
1150             codeBlock->replacement()->jettison(Profiler::JettisonDueToBaselineLoopReoptimizationTrigger, CountReoptimization);
1151             return encodeResult(0, 0);
1152         }
1153     } else {
1154         if (!codeBlock->shouldOptimizeNow()) {
1155             if (Options::verboseOSR()) {
1156                 dataLog(
1157                     "Delaying optimization for ", *codeBlock,
1158                     " because of insufficient profiling.\n");
1159             }
1160             return encodeResult(0, 0);
1161         }
1162
1163         if (Options::verboseOSR())
1164             dataLog("Triggering optimized compilation of ", *codeBlock, "\n");
1165
1166         unsigned numVarsWithValues;
1167         if (bytecodeIndex)
1168             numVarsWithValues = codeBlock->m_numVars;
1169         else
1170             numVarsWithValues = 0;
1171         Operands<JSValue> mustHandleValues(codeBlock->numParameters(), numVarsWithValues);
1172         for (size_t i = 0; i < mustHandleValues.size(); ++i) {
1173             int operand = mustHandleValues.operandForIndex(i);
1174             if (operandIsArgument(operand)
1175                 && !VirtualRegister(operand).toArgument()
1176                 && codeBlock->codeType() == FunctionCode
1177                 && codeBlock->specializationKind() == CodeForConstruct) {
1178                 // Ugh. If we're in a constructor, the 'this' argument may hold garbage. It will
1179                 // also never be used. It doesn't matter what we put into the value for this,
1180                 // but it has to be an actual value that can be grokked by subsequent DFG passes,
1181                 // so we sanitize it here by turning it into Undefined.
1182                 mustHandleValues[i] = jsUndefined();
1183             } else
1184                 mustHandleValues[i] = exec->uncheckedR(operand).jsValue();
1185         }
1186
1187         RefPtr<CodeBlock> replacementCodeBlock = codeBlock->newReplacement();
1188         CompilationResult result = DFG::compile(
1189             vm, replacementCodeBlock.get(), 0, DFG::DFGMode, bytecodeIndex,
1190             mustHandleValues, JITToDFGDeferredCompilationCallback::create());
1191         
1192         if (result != CompilationSuccessful) {
1193             ASSERT(result == CompilationDeferred || replacementCodeBlock->hasOneRef());
1194             return encodeResult(0, 0);
1195         }
1196     }
1197     
1198     CodeBlock* optimizedCodeBlock = codeBlock->replacement();
1199     ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
1200     
1201     if (void* dataBuffer = DFG::prepareOSREntry(exec, optimizedCodeBlock, bytecodeIndex)) {
1202         if (Options::verboseOSR()) {
1203             dataLog(
1204                 "Performing OSR ", *codeBlock, " -> ", *optimizedCodeBlock, ".\n");
1205         }
1206
1207         codeBlock->optimizeSoon();
1208         return encodeResult(vm.getCTIStub(DFG::osrEntryThunkGenerator).code().executableAddress(), dataBuffer);
1209     }
1210
1211     if (Options::verboseOSR()) {
1212         dataLog(
1213             "Optimizing ", *codeBlock, " -> ", *codeBlock->replacement(),
1214             " succeeded, OSR failed, after a delay of ",
1215             codeBlock->optimizationDelayCounter(), ".\n");
1216     }
1217
1218     // Count the OSR failure as a speculation failure. If this happens a lot, then
1219     // reoptimize.
1220     optimizedCodeBlock->countOSRExit();
1221
1222     // We are a lot more conservative about triggering reoptimization after OSR failure than
1223     // before it. If we enter the optimize_from_loop trigger with a bucket full of fail
1224     // already, then we really would like to reoptimize immediately. But this case covers
1225     // something else: there weren't many (or any) speculation failures before, but we just
1226     // failed to enter the speculative code because some variable had the wrong value or
1227     // because the OSR code decided for any spurious reason that it did not want to OSR
1228     // right now. So, we only trigger reoptimization only upon the more conservative (non-loop)
1229     // reoptimization trigger.
1230     if (optimizedCodeBlock->shouldReoptimizeNow()) {
1231         if (Options::verboseOSR()) {
1232             dataLog(
1233                 "Triggering reoptimization of ", *codeBlock, " -> ",
1234                 *codeBlock->replacement(), " (after OSR fail).\n");
1235         }
1236         optimizedCodeBlock->jettison(Profiler::JettisonDueToBaselineLoopReoptimizationTriggerOnOSREntryFail, CountReoptimization);
1237         return encodeResult(0, 0);
1238     }
1239
1240     // OSR failed this time, but it might succeed next time! Let the code run a bit
1241     // longer and then try again.
1242     codeBlock->optimizeAfterWarmUp();
1243     
1244     return encodeResult(0, 0);
1245 }
1246 #endif
1247
1248 void JIT_OPERATION operationPutByIndex(ExecState* exec, EncodedJSValue encodedArrayValue, int32_t index, EncodedJSValue encodedValue)
1249 {
1250     VM& vm = exec->vm();
1251     NativeCallFrameTracer tracer(&vm, exec);
1252
1253     JSValue arrayValue = JSValue::decode(encodedArrayValue);
1254     ASSERT(isJSArray(arrayValue));
1255     asArray(arrayValue)->putDirectIndex(exec, index, JSValue::decode(encodedValue));
1256 }
1257
1258 #if USE(JSVALUE64)
1259 void JIT_OPERATION operationPutGetterSetter(ExecState* exec, EncodedJSValue encodedObjectValue, Identifier* identifier, EncodedJSValue encodedGetterValue, EncodedJSValue encodedSetterValue)
1260 {
1261     VM& vm = exec->vm();
1262     NativeCallFrameTracer tracer(&vm, exec);
1263
1264     ASSERT(JSValue::decode(encodedObjectValue).isObject());
1265     JSObject* baseObj = asObject(JSValue::decode(encodedObjectValue));
1266
1267     GetterSetter* accessor = GetterSetter::create(vm, exec->lexicalGlobalObject());
1268
1269     JSValue getter = JSValue::decode(encodedGetterValue);
1270     JSValue setter = JSValue::decode(encodedSetterValue);
1271     ASSERT(getter.isObject() || getter.isUndefined());
1272     ASSERT(setter.isObject() || setter.isUndefined());
1273     ASSERT(getter.isObject() || setter.isObject());
1274
1275     if (!getter.isUndefined())
1276         accessor->setGetter(vm, exec->lexicalGlobalObject(), asObject(getter));
1277     if (!setter.isUndefined())
1278         accessor->setSetter(vm, exec->lexicalGlobalObject(), asObject(setter));
1279     baseObj->putDirectAccessor(exec, *identifier, accessor, Accessor);
1280 }
1281 #else
1282 void JIT_OPERATION operationPutGetterSetter(ExecState* exec, JSCell* object, Identifier* identifier, JSCell* getter, JSCell* setter)
1283 {
1284     VM& vm = exec->vm();
1285     NativeCallFrameTracer tracer(&vm, exec);
1286
1287     ASSERT(object && object->isObject());
1288     JSObject* baseObj = object->getObject();
1289
1290     GetterSetter* accessor = GetterSetter::create(vm, exec->lexicalGlobalObject());
1291
1292     ASSERT(!getter || getter->isObject());
1293     ASSERT(!setter || setter->isObject());
1294     ASSERT(getter || setter);
1295
1296     if (getter)
1297         accessor->setGetter(vm, exec->lexicalGlobalObject(), getter->getObject());
1298     if (setter)
1299         accessor->setSetter(vm, exec->lexicalGlobalObject(), setter->getObject());
1300     baseObj->putDirectAccessor(exec, *identifier, accessor, Accessor);
1301 }
1302 #endif
1303
1304 void JIT_OPERATION operationPushNameScope(ExecState* exec, int32_t dst, Identifier* identifier, EncodedJSValue encodedValue, int32_t attibutes, int32_t type)
1305 {
1306     VM& vm = exec->vm();
1307     NativeCallFrameTracer tracer(&vm, exec);
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 new scope.
1311     JSScope* currentScope = exec->uncheckedR(dst).Register::scope();
1312     JSNameScope::Type scopeType = static_cast<JSNameScope::Type>(type);
1313     JSNameScope* scope = JSNameScope::create(exec, currentScope, *identifier, JSValue::decode(encodedValue), attibutes, scopeType);
1314
1315     // FIXME: This won't work if this operation is called from the DFG or FTL.
1316     // This should be changed to return the new scope.
1317     exec->uncheckedR(dst) = scope;
1318 }
1319
1320 #if USE(JSVALUE32_64)
1321 void JIT_OPERATION operationPushCatchScope(ExecState* exec, int32_t dst, Identifier* identifier, EncodedJSValue encodedValue, int32_t attibutes)
1322 {
1323     operationPushNameScope(exec, dst, identifier, encodedValue, attibutes, JSNameScope::CatchScope);
1324 }
1325
1326 void JIT_OPERATION operationPushFunctionNameScope(ExecState* exec, int32_t dst, Identifier* identifier, EncodedJSValue encodedValue, int32_t attibutes)
1327 {
1328     operationPushNameScope(exec, dst, identifier, encodedValue, attibutes, JSNameScope::FunctionNameScope);
1329 }
1330 #endif
1331
1332 void JIT_OPERATION operationPushWithScope(ExecState* exec, int32_t dst, EncodedJSValue encodedValue)
1333 {
1334     VM& vm = exec->vm();
1335     NativeCallFrameTracer tracer(&vm, exec);
1336
1337     JSObject* o = JSValue::decode(encodedValue).toObject(exec);
1338     if (vm.exception())
1339         return;
1340
1341     // FIXME: This won't work if this operation is called from the DFG or FTL.
1342     // This should be changed to pass in the old scope and return the new scope.
1343     JSScope* currentScope = exec->uncheckedR(dst).Register::scope();
1344     exec->uncheckedR(dst) = JSWithScope::create(exec, o, currentScope);
1345 }
1346
1347 void JIT_OPERATION operationPopScope(ExecState* exec, int32_t scopeReg)
1348 {
1349     VM& vm = exec->vm();
1350     NativeCallFrameTracer tracer(&vm, exec);
1351
1352     JSScope* scope = exec->uncheckedR(scopeReg).Register::scope();
1353     exec->uncheckedR(scopeReg) = scope->next();
1354 }
1355
1356 void JIT_OPERATION operationProfileDidCall(ExecState* exec, EncodedJSValue encodedValue)
1357 {
1358     VM& vm = exec->vm();
1359     NativeCallFrameTracer tracer(&vm, exec);
1360
1361     if (LegacyProfiler* profiler = vm.enabledProfiler())
1362         profiler->didExecute(exec, JSValue::decode(encodedValue));
1363 }
1364
1365 void JIT_OPERATION operationProfileWillCall(ExecState* exec, EncodedJSValue encodedValue)
1366 {
1367     VM& vm = exec->vm();
1368     NativeCallFrameTracer tracer(&vm, exec);
1369
1370     if (LegacyProfiler* profiler = vm.enabledProfiler())
1371         profiler->willExecute(exec, JSValue::decode(encodedValue));
1372 }
1373
1374 EncodedJSValue JIT_OPERATION operationCheckHasInstance(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBaseVal)
1375 {
1376     VM& vm = exec->vm();
1377     NativeCallFrameTracer tracer(&vm, exec);
1378
1379     JSValue value = JSValue::decode(encodedValue);
1380     JSValue baseVal = JSValue::decode(encodedBaseVal);
1381
1382     if (baseVal.isObject()) {
1383         JSObject* baseObject = asObject(baseVal);
1384         ASSERT(!baseObject->structure(vm)->typeInfo().implementsDefaultHasInstance());
1385         if (baseObject->structure(vm)->typeInfo().implementsHasInstance()) {
1386             bool result = baseObject->methodTable(vm)->customHasInstance(baseObject, exec, value);
1387             return JSValue::encode(jsBoolean(result));
1388         }
1389     }
1390
1391     vm.throwException(exec, createInvalidParameterError(exec, "instanceof", baseVal));
1392     return JSValue::encode(JSValue());
1393 }
1394
1395 JSCell* JIT_OPERATION operationCreateActivation(ExecState* exec, JSScope* currentScope, int32_t offset)
1396 {
1397     VM& vm = exec->vm();
1398     NativeCallFrameTracer tracer(&vm, exec);
1399     JSLexicalEnvironment* lexicalEnvironment = JSLexicalEnvironment::create(vm, exec, exec->registers() + offset, currentScope, exec->codeBlock());
1400     return lexicalEnvironment;
1401 }
1402
1403 // FIXME: This is a temporary thunk for the DFG until we add the lexicalEnvironment operand to the DFG CreateArguments node.
1404 JSCell* JIT_OPERATION operationCreateArgumentsForDFG(ExecState* exec)
1405 {
1406     JSLexicalEnvironment* lexicalEnvironment = exec->lexicalEnvironmentOrNullptr();
1407     return operationCreateArguments(exec, lexicalEnvironment);
1408 }
1409     
1410 JSCell* JIT_OPERATION operationCreateArguments(ExecState* exec, JSLexicalEnvironment* lexicalEnvironment)
1411 {
1412     VM& vm = exec->vm();
1413     NativeCallFrameTracer tracer(&vm, exec);
1414     // NB: This needs to be exceedingly careful with top call frame tracking, since it
1415     // may be called from OSR exit, while the state of the call stack is bizarre.
1416     Arguments* result = Arguments::create(vm, exec, lexicalEnvironment);
1417     ASSERT(!vm.exception());
1418     return result;
1419 }
1420
1421 JSCell* JIT_OPERATION operationCreateArgumentsDuringOSRExit(ExecState* exec)
1422 {
1423     DeferGCForAWhile(exec->vm().heap);
1424     JSLexicalEnvironment* lexicalEnvironment = exec->lexicalEnvironmentOrNullptr();
1425     return operationCreateArguments(exec, lexicalEnvironment);
1426 }
1427
1428 EncodedJSValue JIT_OPERATION operationGetArgumentsLength(ExecState* exec, int32_t argumentsRegister)
1429 {
1430     VM& vm = exec->vm();
1431     NativeCallFrameTracer tracer(&vm, exec);
1432     // Here we can assume that the argumernts were created. Because otherwise the JIT code would
1433     // have not made this call.
1434     Identifier ident(&vm, "length");
1435     JSValue baseValue = exec->uncheckedR(argumentsRegister).jsValue();
1436     PropertySlot slot(baseValue);
1437     return JSValue::encode(baseValue.get(exec, ident, slot));
1438 }
1439
1440 }
1441
1442 static JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript, ReturnAddressPtr returnAddress)
1443 {
1444     if (LIKELY(baseValue.isCell() && subscript.isString())) {
1445         VM& vm = exec->vm();
1446         Structure& structure = *baseValue.asCell()->structure(vm);
1447         if (JSCell::canUseFastGetOwnProperty(structure)) {
1448             if (AtomicStringImpl* existingAtomicString = asString(subscript)->toExistingAtomicString(exec)) {
1449                 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString))
1450                     return result;
1451             }
1452         }
1453     }
1454
1455     if (subscript.isUInt32()) {
1456         uint32_t i = subscript.asUInt32();
1457         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) {
1458             ctiPatchCallByReturnAddress(exec->codeBlock(), returnAddress, FunctionPtr(operationGetByValString));
1459             return asString(baseValue)->getIndex(exec, i);
1460         }
1461         return baseValue.get(exec, i);
1462     }
1463
1464     PropertyName property = subscript.toPropertyKey(exec);
1465     return baseValue.get(exec, property);
1466 }
1467
1468 extern "C" {
1469     
1470 EncodedJSValue JIT_OPERATION operationGetByValGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
1471 {
1472     VM& vm = exec->vm();
1473     NativeCallFrameTracer tracer(&vm, exec);
1474     JSValue baseValue = JSValue::decode(encodedBase);
1475     JSValue subscript = JSValue::decode(encodedSubscript);
1476
1477     JSValue result = getByVal(exec, baseValue, subscript, ReturnAddressPtr(OUR_RETURN_ADDRESS));
1478     return JSValue::encode(result);
1479 }
1480
1481 EncodedJSValue JIT_OPERATION operationGetByValDefault(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
1482 {
1483     VM& vm = exec->vm();
1484     NativeCallFrameTracer tracer(&vm, exec);
1485     JSValue baseValue = JSValue::decode(encodedBase);
1486     JSValue subscript = JSValue::decode(encodedSubscript);
1487     
1488     if (baseValue.isObject() && subscript.isInt32()) {
1489         // See if it's worth optimizing this at all.
1490         JSObject* object = asObject(baseValue);
1491         bool didOptimize = false;
1492
1493         unsigned bytecodeOffset = exec->locationAsBytecodeOffset();
1494         ASSERT(bytecodeOffset);
1495         ByValInfo& byValInfo = exec->codeBlock()->getByValInfo(bytecodeOffset - 1);
1496         ASSERT(!byValInfo.stubRoutine);
1497         
1498         if (hasOptimizableIndexing(object->structure(vm))) {
1499             // Attempt to optimize.
1500             JITArrayMode arrayMode = jitArrayModeForStructure(object->structure(vm));
1501             if (arrayMode != byValInfo.arrayMode) {
1502                 JIT::compileGetByVal(&vm, exec->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
1503                 didOptimize = true;
1504             }
1505         }
1506         
1507         if (!didOptimize) {
1508             // If we take slow path more than 10 times without patching then make sure we
1509             // never make that mistake again. Or, if we failed to patch and we have some object
1510             // that intercepts indexed get, then don't even wait until 10 times. For cases
1511             // where we see non-index-intercepting objects, this gives 10 iterations worth of
1512             // opportunity for us to observe that the get_by_val may be polymorphic.
1513             if (++byValInfo.slowPathCount >= 10
1514                 || object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
1515                 // Don't ever try to optimize.
1516                 ctiPatchCallByReturnAddress(exec->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationGetByValGeneric));
1517             }
1518         }
1519     }
1520     
1521     JSValue result = getByVal(exec, baseValue, subscript, ReturnAddressPtr(OUR_RETURN_ADDRESS));
1522     return JSValue::encode(result);
1523 }
1524     
1525 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyDefault(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     bool didOptimize = false;
1537
1538     unsigned bytecodeOffset = exec->locationAsBytecodeOffset();
1539     ASSERT(bytecodeOffset);
1540     ByValInfo& byValInfo = exec->codeBlock()->getByValInfo(bytecodeOffset - 1);
1541     ASSERT(!byValInfo.stubRoutine);
1542     
1543     if (hasOptimizableIndexing(object->structure(vm))) {
1544         // Attempt to optimize.
1545         JITArrayMode arrayMode = jitArrayModeForStructure(object->structure(vm));
1546         if (arrayMode != byValInfo.arrayMode) {
1547             JIT::compileHasIndexedProperty(&vm, exec->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
1548             didOptimize = true;
1549         }
1550     }
1551     
1552     if (!didOptimize) {
1553         // If we take slow path more than 10 times without patching then make sure we
1554         // never make that mistake again. Or, if we failed to patch and we have some object
1555         // that intercepts indexed get, then don't even wait until 10 times. For cases
1556         // where we see non-index-intercepting objects, this gives 10 iterations worth of
1557         // opportunity for us to observe that the get_by_val may be polymorphic.
1558         if (++byValInfo.slowPathCount >= 10
1559             || object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
1560             // Don't ever try to optimize.
1561             ctiPatchCallByReturnAddress(exec->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationHasIndexedPropertyGeneric)); 
1562         }
1563     }
1564     
1565     return JSValue::encode(jsBoolean(object->hasProperty(exec, subscript.asUInt32())));
1566 }
1567     
1568 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
1569 {
1570     VM& vm = exec->vm();
1571     NativeCallFrameTracer tracer(&vm, exec);
1572     JSValue baseValue = JSValue::decode(encodedBase);
1573     JSValue subscript = JSValue::decode(encodedSubscript);
1574     
1575     ASSERT(baseValue.isObject());
1576     ASSERT(subscript.isUInt32());
1577
1578     JSObject* object = asObject(baseValue);
1579     return JSValue::encode(jsBoolean(object->hasProperty(exec, subscript.asUInt32())));
1580 }
1581     
1582 EncodedJSValue JIT_OPERATION operationGetByValString(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
1583 {
1584     VM& vm = exec->vm();
1585     NativeCallFrameTracer tracer(&vm, exec);
1586     JSValue baseValue = JSValue::decode(encodedBase);
1587     JSValue subscript = JSValue::decode(encodedSubscript);
1588     
1589     JSValue result;
1590     if (LIKELY(subscript.isUInt32())) {
1591         uint32_t i = subscript.asUInt32();
1592         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
1593             result = asString(baseValue)->getIndex(exec, i);
1594         else {
1595             result = baseValue.get(exec, i);
1596             if (!isJSString(baseValue))
1597                 ctiPatchCallByReturnAddress(exec->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationGetByValDefault));
1598         }
1599     } else {
1600         PropertyName property = subscript.toPropertyKey(exec);
1601         result = baseValue.get(exec, property);
1602     }
1603
1604     return JSValue::encode(result);
1605 }
1606
1607 void JIT_OPERATION operationTearOffArguments(ExecState* exec, JSCell* argumentsCell, JSCell*)
1608 {
1609     ASSERT(exec->codeBlock()->usesArguments());
1610     jsCast<Arguments*>(argumentsCell)->tearOff(exec);
1611 }
1612
1613 EncodedJSValue JIT_OPERATION operationDeleteById(ExecState* exec, EncodedJSValue encodedBase, const Identifier* identifier)
1614 {
1615     VM& vm = exec->vm();
1616     NativeCallFrameTracer tracer(&vm, exec);
1617
1618     JSObject* baseObj = JSValue::decode(encodedBase).toObject(exec);
1619     bool couldDelete = baseObj->methodTable(vm)->deleteProperty(baseObj, exec, *identifier);
1620     JSValue result = jsBoolean(couldDelete);
1621     if (!couldDelete && exec->codeBlock()->isStrictMode())
1622         vm.throwException(exec, createTypeError(exec, ASCIILiteral("Unable to delete property.")));
1623     return JSValue::encode(result);
1624 }
1625
1626 EncodedJSValue JIT_OPERATION operationInstanceOf(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedProto)
1627 {
1628     VM& vm = exec->vm();
1629     NativeCallFrameTracer tracer(&vm, exec);
1630     JSValue value = JSValue::decode(encodedValue);
1631     JSValue proto = JSValue::decode(encodedProto);
1632     
1633     ASSERT(!value.isObject() || !proto.isObject());
1634
1635     bool result = JSObject::defaultHasInstance(exec, value, proto);
1636     return JSValue::encode(jsBoolean(result));
1637 }
1638
1639 CallFrame* JIT_OPERATION operationSizeFrameForVarargs(ExecState* exec, EncodedJSValue encodedArguments, int32_t firstFreeRegister, int32_t firstVarArgOffset)
1640 {
1641     VM& vm = exec->vm();
1642     NativeCallFrameTracer tracer(&vm, exec);
1643     JSStack* stack = &exec->interpreter()->stack();
1644     JSValue arguments = JSValue::decode(encodedArguments);
1645     CallFrame* newCallFrame = sizeFrameForVarargs(exec, stack, arguments, firstFreeRegister, firstVarArgOffset);
1646     return newCallFrame;
1647 }
1648
1649 CallFrame* JIT_OPERATION operationLoadVarargs(ExecState* exec, CallFrame* newCallFrame, EncodedJSValue encodedThis, EncodedJSValue encodedArguments, int32_t firstVarArgOffset)
1650 {
1651     VM& vm = exec->vm();
1652     NativeCallFrameTracer tracer(&vm, exec);
1653     JSValue thisValue = JSValue::decode(encodedThis);
1654     JSValue arguments = JSValue::decode(encodedArguments);
1655     loadVarargs(exec, newCallFrame, thisValue, arguments, firstVarArgOffset);
1656     return newCallFrame;
1657 }
1658
1659 EncodedJSValue JIT_OPERATION operationToObject(ExecState* exec, EncodedJSValue value)
1660 {
1661     VM& vm = exec->vm();
1662     NativeCallFrameTracer tracer(&vm, exec);
1663     return JSValue::encode(JSValue::decode(value).toObject(exec));
1664 }
1665
1666 char* JIT_OPERATION operationSwitchCharWithUnknownKeyType(ExecState* exec, EncodedJSValue encodedKey, size_t tableIndex)
1667 {
1668     VM& vm = exec->vm();
1669     NativeCallFrameTracer tracer(&vm, exec);
1670     JSValue key = JSValue::decode(encodedKey);
1671     CodeBlock* codeBlock = exec->codeBlock();
1672
1673     SimpleJumpTable& jumpTable = codeBlock->switchJumpTable(tableIndex);
1674     void* result = jumpTable.ctiDefault.executableAddress();
1675
1676     if (key.isString()) {
1677         StringImpl* value = asString(key)->value(exec).impl();
1678         if (value->length() == 1)
1679             result = jumpTable.ctiForValue((*value)[0]).executableAddress();
1680     }
1681
1682     return reinterpret_cast<char*>(result);
1683 }
1684
1685 char* JIT_OPERATION operationSwitchImmWithUnknownKeyType(ExecState* exec, EncodedJSValue encodedKey, size_t tableIndex)
1686 {
1687     VM& vm = exec->vm();
1688     NativeCallFrameTracer tracer(&vm, exec);
1689     JSValue key = JSValue::decode(encodedKey);
1690     CodeBlock* codeBlock = exec->codeBlock();
1691
1692     SimpleJumpTable& jumpTable = codeBlock->switchJumpTable(tableIndex);
1693     void* result;
1694     if (key.isInt32())
1695         result = jumpTable.ctiForValue(key.asInt32()).executableAddress();
1696     else if (key.isDouble() && key.asDouble() == static_cast<int32_t>(key.asDouble()))
1697         result = jumpTable.ctiForValue(static_cast<int32_t>(key.asDouble())).executableAddress();
1698     else
1699         result = jumpTable.ctiDefault.executableAddress();
1700     return reinterpret_cast<char*>(result);
1701 }
1702
1703 char* JIT_OPERATION operationSwitchStringWithUnknownKeyType(ExecState* exec, EncodedJSValue encodedKey, size_t tableIndex)
1704 {
1705     VM& vm = exec->vm();
1706     NativeCallFrameTracer tracer(&vm, exec);
1707     JSValue key = JSValue::decode(encodedKey);
1708     CodeBlock* codeBlock = exec->codeBlock();
1709
1710     void* result;
1711     StringJumpTable& jumpTable = codeBlock->stringSwitchJumpTable(tableIndex);
1712
1713     if (key.isString()) {
1714         StringImpl* value = asString(key)->value(exec).impl();
1715         result = jumpTable.ctiForValue(value).executableAddress();
1716     } else
1717         result = jumpTable.ctiDefault.executableAddress();
1718
1719     return reinterpret_cast<char*>(result);
1720 }
1721
1722 EncodedJSValue JIT_OPERATION operationResolveScope(ExecState* exec, int32_t scopeReg, int32_t identifierIndex)
1723 {
1724     VM& vm = exec->vm();
1725     NativeCallFrameTracer tracer(&vm, exec);
1726     const Identifier& ident = exec->codeBlock()->identifier(identifierIndex);
1727     JSScope* scope = exec->uncheckedR(scopeReg).Register::scope();
1728     return JSValue::encode(JSScope::resolve(exec, scope, ident));
1729 }
1730
1731 EncodedJSValue JIT_OPERATION operationGetFromScope(ExecState* exec, Instruction* bytecodePC)
1732 {
1733     VM& vm = exec->vm();
1734     NativeCallFrameTracer tracer(&vm, exec);
1735     CodeBlock* codeBlock = exec->codeBlock();
1736     Instruction* pc = bytecodePC;
1737
1738     const Identifier& ident = codeBlock->identifier(pc[3].u.operand);
1739     JSObject* scope = jsCast<JSObject*>(exec->uncheckedR(pc[2].u.operand).jsValue());
1740     ResolveModeAndType modeAndType(pc[4].u.operand);
1741
1742     PropertySlot slot(scope);
1743     if (!scope->getPropertySlot(exec, ident, slot)) {
1744         if (modeAndType.mode() == ThrowIfNotFound)
1745             vm.throwException(exec, createUndefinedVariableError(exec, ident));
1746         return JSValue::encode(jsUndefined());
1747     }
1748
1749     // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time.
1750     if (slot.isCacheableValue() && slot.slotBase() == scope && scope->structure(vm)->propertyAccessesAreCacheable()) {
1751         if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) {
1752             Structure* structure = scope->structure(vm);
1753             {
1754                 ConcurrentJITLocker locker(codeBlock->m_lock);
1755                 pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), structure);
1756                 pc[6].u.operand = slot.cachedOffset();
1757             }
1758             structure->startWatchingPropertyForReplacements(vm, slot.cachedOffset());
1759         }
1760     }
1761
1762     return JSValue::encode(slot.getValue(exec, ident));
1763 }
1764
1765 void JIT_OPERATION operationPutToScope(ExecState* exec, Instruction* bytecodePC)
1766 {
1767     VM& vm = exec->vm();
1768     NativeCallFrameTracer tracer(&vm, exec);
1769     Instruction* pc = bytecodePC;
1770
1771     CodeBlock* codeBlock = exec->codeBlock();
1772     const Identifier& ident = codeBlock->identifier(pc[2].u.operand);
1773     JSObject* scope = jsCast<JSObject*>(exec->uncheckedR(pc[1].u.operand).jsValue());
1774     JSValue value = exec->r(pc[3].u.operand).jsValue();
1775     ResolveModeAndType modeAndType = ResolveModeAndType(pc[4].u.operand);
1776     if (modeAndType.type() == LocalClosureVar) {
1777         JSLexicalEnvironment* environment = jsCast<JSLexicalEnvironment*>(scope);
1778         environment->registerAt(pc[6].u.operand).set(vm, environment, value);
1779         if (VariableWatchpointSet* set = pc[5].u.watchpointSet)
1780             set->notifyWrite(vm, value, "Executed op_put_scope<LocalClosureVar>");
1781         return;
1782     }
1783     if (modeAndType.mode() == ThrowIfNotFound && !scope->hasProperty(exec, ident)) {
1784         exec->vm().throwException(exec, createUndefinedVariableError(exec, ident));
1785         return;
1786     }
1787
1788     PutPropertySlot slot(scope, codeBlock->isStrictMode());
1789     scope->methodTable()->put(scope, exec, ident, value, slot);
1790     
1791     if (exec->vm().exception())
1792         return;
1793
1794     CommonSlowPaths::tryCachePutToScopeGlobal(exec, codeBlock, pc, scope, modeAndType, slot);
1795 }
1796
1797 void JIT_OPERATION operationThrow(ExecState* exec, EncodedJSValue encodedExceptionValue)
1798 {
1799     VM* vm = &exec->vm();
1800     NativeCallFrameTracer tracer(vm, exec);
1801
1802     JSValue exceptionValue = JSValue::decode(encodedExceptionValue);
1803     vm->throwException(exec, exceptionValue);
1804
1805     // Results stored out-of-band in vm.targetMachinePCForThrow, vm.callFrameForThrow & vm.vmEntryFrameForThrow
1806     genericUnwind(vm, exec, exceptionValue);
1807 }
1808
1809 void JIT_OPERATION operationFlushWriteBarrierBuffer(ExecState* exec, JSCell* cell)
1810 {
1811     VM* vm = &exec->vm();
1812     NativeCallFrameTracer tracer(vm, exec);
1813     vm->heap.flushWriteBarrierBuffer(cell);
1814 }
1815
1816 void JIT_OPERATION operationOSRWriteBarrier(ExecState* exec, JSCell* cell)
1817 {
1818     VM* vm = &exec->vm();
1819     NativeCallFrameTracer tracer(vm, exec);
1820     vm->heap.writeBarrier(cell);
1821 }
1822
1823 // NB: We don't include the value as part of the barrier because the write barrier elision
1824 // phase in the DFG only tracks whether the object being stored to has been barriered. It 
1825 // would be much more complicated to try to model the value being stored as well.
1826 void JIT_OPERATION operationUnconditionalWriteBarrier(ExecState* exec, JSCell* cell)
1827 {
1828     VM* vm = &exec->vm();
1829     NativeCallFrameTracer tracer(vm, exec);
1830     vm->heap.writeBarrier(cell);
1831 }
1832
1833 void JIT_OPERATION operationInitGlobalConst(ExecState* exec, Instruction* pc)
1834 {
1835     VM* vm = &exec->vm();
1836     NativeCallFrameTracer tracer(vm, exec);
1837
1838     JSValue value = exec->r(pc[2].u.operand).jsValue();
1839     pc[1].u.registerPointer->set(*vm, exec->codeBlock()->globalObject(), value);
1840 }
1841
1842 void JIT_OPERATION lookupExceptionHandler(VM* vm, ExecState* exec)
1843 {
1844     NativeCallFrameTracer tracer(vm, exec);
1845
1846     JSValue exceptionValue = vm->exception();
1847     ASSERT(exceptionValue);
1848     
1849     genericUnwind(vm, exec, exceptionValue);
1850     ASSERT(vm->targetMachinePCForThrow);
1851 }
1852
1853 void JIT_OPERATION lookupExceptionHandlerFromCallerFrame(VM* vm, ExecState* exec)
1854 {
1855     VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
1856     CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
1857     ASSERT(callerFrame);
1858
1859     NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
1860
1861     JSValue exceptionValue = vm->exception();
1862     ASSERT(exceptionValue);
1863     
1864     genericUnwind(vm, callerFrame, exceptionValue);
1865     ASSERT(vm->targetMachinePCForThrow);
1866 }
1867
1868 void JIT_OPERATION operationVMHandleException(ExecState* exec)
1869 {
1870     VM* vm = &exec->vm();
1871     NativeCallFrameTracer tracer(vm, exec);
1872
1873     genericUnwind(vm, exec, vm->exception());
1874 }
1875
1876 // This function "should" just take the ExecState*, but doing so would make it more difficult
1877 // to call from exception check sites. So, unlike all of our other functions, we allow
1878 // ourselves to play some gnarly ABI tricks just to simplify the calling convention. This is
1879 // particularly safe here since this is never called on the critical path - it's only for
1880 // testing.
1881 void JIT_OPERATION operationExceptionFuzz()
1882 {
1883     // This probably "just works" for GCC also, but I haven't tried.
1884 #if COMPILER(CLANG)
1885     ExecState* exec = static_cast<ExecState*>(__builtin_frame_address(1));
1886     void* returnPC = __builtin_return_address(0);
1887     doExceptionFuzzing(exec, "JITOperations", returnPC);
1888 #endif // COMPILER(CLANG)
1889 }
1890
1891 int32_t JIT_OPERATION operationGetEnumerableLength(ExecState* exec, JSCell* baseCell)
1892 {
1893     VM& vm = exec->vm();
1894     NativeCallFrameTracer tracer(&vm, exec);
1895     JSObject* base = baseCell->toObject(exec, exec->lexicalGlobalObject());
1896     return base->methodTable(vm)->getEnumerableLength(exec, base);
1897 }
1898
1899 EncodedJSValue JIT_OPERATION operationHasGenericProperty(ExecState* exec, EncodedJSValue encodedBaseValue, JSCell* propertyName)
1900 {
1901     VM& vm = exec->vm();
1902     NativeCallFrameTracer tracer(&vm, exec);
1903     JSValue baseValue = JSValue::decode(encodedBaseValue);
1904     if (baseValue.isUndefinedOrNull())
1905         return JSValue::encode(jsBoolean(false));
1906
1907     JSObject* base = baseValue.toObject(exec);
1908     return JSValue::encode(jsBoolean(base->hasProperty(exec, asString(propertyName)->toIdentifier(exec))));
1909 }
1910
1911 EncodedJSValue JIT_OPERATION operationHasIndexedProperty(ExecState* exec, JSCell* baseCell, int32_t subscript)
1912 {
1913     VM& vm = exec->vm();
1914     NativeCallFrameTracer tracer(&vm, exec);
1915     JSObject* object = baseCell->toObject(exec, exec->lexicalGlobalObject());
1916     return JSValue::encode(jsBoolean(object->hasProperty(exec, subscript)));
1917 }
1918     
1919 JSCell* JIT_OPERATION operationGetStructurePropertyEnumerator(ExecState* exec, JSCell* cell, int32_t length)
1920 {
1921     VM& vm = exec->vm();
1922     NativeCallFrameTracer tracer(&vm, exec);
1923         
1924     JSObject* base = cell->toObject(exec, exec->lexicalGlobalObject());
1925     ASSERT(length >= 0);
1926
1927     return structurePropertyNameEnumerator(exec, base, static_cast<uint32_t>(length));
1928 }
1929
1930 JSCell* JIT_OPERATION operationGetGenericPropertyEnumerator(ExecState* exec, JSCell* baseCell, int32_t length, JSCell* structureEnumeratorCell)
1931 {
1932     VM& vm = exec->vm();
1933     NativeCallFrameTracer tracer(&vm, exec);
1934     
1935     JSObject* base = baseCell->toObject(exec, exec->lexicalGlobalObject());
1936     ASSERT(length >= 0);
1937
1938     return genericPropertyNameEnumerator(exec, base, length, jsCast<JSPropertyNameEnumerator*>(structureEnumeratorCell));
1939 }
1940
1941 EncodedJSValue JIT_OPERATION operationNextEnumeratorPname(ExecState* exec, JSCell* enumeratorCell, int32_t index)
1942 {
1943     VM& vm = exec->vm();
1944     NativeCallFrameTracer tracer(&vm, exec);
1945     JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(enumeratorCell);
1946     JSString* propertyName = enumerator->propertyNameAtIndex(index);
1947     return JSValue::encode(propertyName ? propertyName : jsNull());
1948 }
1949
1950 JSCell* JIT_OPERATION operationToIndexString(ExecState* exec, int32_t index)
1951 {
1952     VM& vm = exec->vm();
1953     NativeCallFrameTracer tracer(&vm, exec);
1954     return jsString(exec, Identifier::from(exec, index).string());
1955 }
1956
1957 void JIT_OPERATION operationProcessTypeProfilerLog(ExecState* exec)
1958 {
1959     exec->vm().typeProfilerLog()->processLogEntries(ASCIILiteral("Log Full, called from inside baseline JIT"));
1960 }
1961
1962 } // extern "C"
1963
1964 // Note: getHostCallReturnValueWithExecState() needs to be placed before the
1965 // definition of getHostCallReturnValue() below because the Windows build
1966 // requires it.
1967 extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValueWithExecState(ExecState* exec)
1968 {
1969     if (!exec)
1970         return JSValue::encode(JSValue());
1971     return JSValue::encode(exec->vm().hostCallReturnValue);
1972 }
1973
1974 #if COMPILER(GCC) && CPU(X86_64)
1975 asm (
1976 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1977 HIDE_SYMBOL(getHostCallReturnValue) "\n"
1978 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
1979     "mov %rbp, %rdi\n"
1980     "jmp " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
1981 );
1982
1983 #elif COMPILER(GCC) && CPU(X86)
1984 asm (
1985 ".text" "\n" \
1986 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1987 HIDE_SYMBOL(getHostCallReturnValue) "\n"
1988 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
1989     "push %ebp\n"
1990     "leal -4(%esp), %esp\n"
1991     "push %ebp\n"
1992     "call " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
1993     "leal 8(%esp), %esp\n"
1994     "pop %ebp\n"
1995     "ret\n"
1996 );
1997
1998 #elif COMPILER(GCC) && CPU(ARM_THUMB2)
1999 asm (
2000 ".text" "\n"
2001 ".align 2" "\n"
2002 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
2003 HIDE_SYMBOL(getHostCallReturnValue) "\n"
2004 ".thumb" "\n"
2005 ".thumb_func " THUMB_FUNC_PARAM(getHostCallReturnValue) "\n"
2006 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
2007     "mov r0, r7" "\n"
2008     "b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
2009 );
2010
2011 #elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
2012 asm (
2013 ".text" "\n"
2014 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
2015 HIDE_SYMBOL(getHostCallReturnValue) "\n"
2016 INLINE_ARM_FUNCTION(getHostCallReturnValue)
2017 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
2018     "mov r0, r11" "\n"
2019     "b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
2020 );
2021
2022 #elif CPU(ARM64)
2023 asm (
2024 ".text" "\n"
2025 ".align 2" "\n"
2026 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
2027 HIDE_SYMBOL(getHostCallReturnValue) "\n"
2028 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
2029      "mov x0, x29" "\n"
2030      "b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
2031 );
2032
2033 #elif COMPILER(GCC) && CPU(MIPS)
2034
2035 #if WTF_MIPS_PIC
2036 #define LOAD_FUNCTION_TO_T9(function) \
2037         ".set noreorder" "\n" \
2038         ".cpload $25" "\n" \
2039         ".set reorder" "\n" \
2040         "la $t9, " LOCAL_REFERENCE(function) "\n"
2041 #else
2042 #define LOAD_FUNCTION_TO_T9(function) "" "\n"
2043 #endif
2044
2045 asm (
2046 ".text" "\n"
2047 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
2048 HIDE_SYMBOL(getHostCallReturnValue) "\n"
2049 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
2050     LOAD_FUNCTION_TO_T9(getHostCallReturnValueWithExecState)
2051     "move $a0, $fp" "\n"
2052     "b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
2053 );
2054
2055 #elif COMPILER(GCC) && CPU(SH4)
2056
2057 #define SH4_SCRATCH_REGISTER "r11"
2058
2059 asm (
2060 ".text" "\n"
2061 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
2062 HIDE_SYMBOL(getHostCallReturnValue) "\n"
2063 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
2064     "mov r14, r4" "\n"
2065     "mov.l 2f, " SH4_SCRATCH_REGISTER "\n"
2066     "braf " SH4_SCRATCH_REGISTER "\n"
2067     "nop" "\n"
2068     "1: .balign 4" "\n"
2069     "2: .long " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "-1b\n"
2070 );
2071
2072 #elif COMPILER(MSVC) && CPU(X86)
2073 extern "C" {
2074     __declspec(naked) EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValue()
2075     {
2076         __asm mov [esp + 4], ebp;
2077         __asm jmp getHostCallReturnValueWithExecState
2078     }
2079 }
2080 #endif
2081
2082 } // namespace JSC
2083
2084 #endif // ENABLE(JIT)