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