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