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