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