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