39516deb3f03aef76014c15bb70872c377754976
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGOperations.cpp
1 /*
2  * Copyright (C) 2011 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 "DFGOperations.h"
28
29 #include "Arguments.h"
30 #include "ButterflyInlines.h"
31 #include "CodeBlock.h"
32 #include "CommonSlowPaths.h"
33 #include "CopiedSpaceInlines.h"
34 #include "DFGOSRExit.h"
35 #include "DFGRepatch.h"
36 #include "DFGThunks.h"
37 #include "HostCallReturnValue.h"
38 #include "GetterSetter.h"
39 #include "Interpreter.h"
40 #include "JIT.h"
41 #include "JITExceptions.h"
42 #include "JSActivation.h"
43 #include "VM.h"
44 #include "JSNameScope.h"
45 #include "NameInstance.h"
46 #include "ObjectConstructor.h"
47 #include "Operations.h"
48 #include "StringConstructor.h"
49 #include <wtf/InlineASM.h>
50
51 #if ENABLE(JIT)
52
53 #if CPU(MIPS)
54 #if WTF_MIPS_PIC
55 #define LOAD_FUNCTION_TO_T9(function) \
56         ".set noreorder" "\n" \
57         ".cpload $25" "\n" \
58         ".set reorder" "\n" \
59         "la $t9, " LOCAL_REFERENCE(function) "\n"
60 #else
61 #define LOAD_FUNCTION_TO_T9(function) "" "\n"
62 #endif
63 #endif
64
65 #if ENABLE(DFG_JIT)
66
67 #if COMPILER(GCC) && CPU(X86_64)
68
69 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, register) \
70     asm( \
71     ".globl " SYMBOL_STRING(function) "\n" \
72     HIDE_SYMBOL(function) "\n" \
73     SYMBOL_STRING(function) ":" "\n" \
74         "mov (%rsp), %" STRINGIZE(register) "\n" \
75         "jmp " LOCAL_REFERENCE(function##WithReturnAddress) "\n" \
76     );
77 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function)    FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, rsi)
78 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function)  FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, rcx)
79 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function)  FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, rcx)
80 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, r8)
81
82 #elif COMPILER(GCC) && CPU(X86)
83
84 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, offset) \
85     asm( \
86     ".text" "\n" \
87     ".globl " SYMBOL_STRING(function) "\n" \
88     HIDE_SYMBOL(function) "\n" \
89     SYMBOL_STRING(function) ":" "\n" \
90         "mov (%esp), %eax\n" \
91         "mov %eax, " STRINGIZE(offset) "(%esp)\n" \
92         "jmp " LOCAL_REFERENCE(function##WithReturnAddress) "\n" \
93     );
94 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function)    FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, 8)
95 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function)  FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, 16)
96 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function)  FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, 20)
97 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, 24)
98
99 #elif COMPILER(GCC) && CPU(ARM_THUMB2)
100
101 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function) \
102     asm ( \
103     ".text" "\n" \
104     ".align 2" "\n" \
105     ".globl " SYMBOL_STRING(function) "\n" \
106     HIDE_SYMBOL(function) "\n" \
107     ".thumb" "\n" \
108     ".thumb_func " THUMB_FUNC_PARAM(function) "\n" \
109     SYMBOL_STRING(function) ":" "\n" \
110         "mov a2, lr" "\n" \
111         "b " LOCAL_REFERENCE(function) "WithReturnAddress" "\n" \
112     );
113
114 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function) \
115     asm ( \
116     ".text" "\n" \
117     ".align 2" "\n" \
118     ".globl " SYMBOL_STRING(function) "\n" \
119     HIDE_SYMBOL(function) "\n" \
120     ".thumb" "\n" \
121     ".thumb_func " THUMB_FUNC_PARAM(function) "\n" \
122     SYMBOL_STRING(function) ":" "\n" \
123         "mov a4, lr" "\n" \
124         "b " LOCAL_REFERENCE(function) "WithReturnAddress" "\n" \
125     );
126
127 // EncodedJSValue in JSVALUE32_64 is a 64-bit integer. When being compiled in ARM EABI, it must be aligned even-numbered register (r0, r2 or [sp]).
128 // As a result, return address will be at a 4-byte further location in the following cases.
129 #if COMPILER_SUPPORTS(EABI) && CPU(ARM)
130 #define INSTRUCTION_STORE_RETURN_ADDRESS_EJI "str lr, [sp, #4]"
131 #define INSTRUCTION_STORE_RETURN_ADDRESS_EJCI "str lr, [sp, #8]"
132 #else
133 #define INSTRUCTION_STORE_RETURN_ADDRESS_EJI "str lr, [sp, #0]"
134 #define INSTRUCTION_STORE_RETURN_ADDRESS_EJCI "str lr, [sp, #4]"
135 #endif
136
137 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function) \
138     asm ( \
139     ".text" "\n" \
140     ".align 2" "\n" \
141     ".globl " SYMBOL_STRING(function) "\n" \
142     HIDE_SYMBOL(function) "\n" \
143     ".thumb" "\n" \
144     ".thumb_func " THUMB_FUNC_PARAM(function) "\n" \
145     SYMBOL_STRING(function) ":" "\n" \
146         INSTRUCTION_STORE_RETURN_ADDRESS_EJI "\n" \
147         "b " LOCAL_REFERENCE(function) "WithReturnAddress" "\n" \
148     );
149
150 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) \
151     asm ( \
152     ".text" "\n" \
153     ".align 2" "\n" \
154     ".globl " SYMBOL_STRING(function) "\n" \
155     HIDE_SYMBOL(function) "\n" \
156     ".thumb" "\n" \
157     ".thumb_func " THUMB_FUNC_PARAM(function) "\n" \
158     SYMBOL_STRING(function) ":" "\n" \
159         INSTRUCTION_STORE_RETURN_ADDRESS_EJCI "\n" \
160         "b " LOCAL_REFERENCE(function) "WithReturnAddress" "\n" \
161     );
162
163 #elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
164
165 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function) \
166     asm ( \
167     ".text" "\n" \
168     ".globl " SYMBOL_STRING(function) "\n" \
169     HIDE_SYMBOL(function) "\n" \
170     INLINE_ARM_FUNCTION(function) \
171     SYMBOL_STRING(function) ":" "\n" \
172         "mov a2, lr" "\n" \
173         "b " LOCAL_REFERENCE(function) "WithReturnAddress" "\n" \
174     );
175
176 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function) \
177     asm ( \
178     ".text" "\n" \
179     ".globl " SYMBOL_STRING(function) "\n" \
180     HIDE_SYMBOL(function) "\n" \
181     INLINE_ARM_FUNCTION(function) \
182     SYMBOL_STRING(function) ":" "\n" \
183         "mov a4, lr" "\n" \
184         "b " LOCAL_REFERENCE(function) "WithReturnAddress" "\n" \
185     );
186
187 // EncodedJSValue in JSVALUE32_64 is a 64-bit integer. When being compiled in ARM EABI, it must be aligned even-numbered register (r0, r2 or [sp]).
188 // As a result, return address will be at a 4-byte further location in the following cases.
189 #if COMPILER_SUPPORTS(EABI) && CPU(ARM)
190 #define INSTRUCTION_STORE_RETURN_ADDRESS_EJI "str lr, [sp, #4]"
191 #define INSTRUCTION_STORE_RETURN_ADDRESS_EJCI "str lr, [sp, #8]"
192 #else
193 #define INSTRUCTION_STORE_RETURN_ADDRESS_EJI "str lr, [sp, #0]"
194 #define INSTRUCTION_STORE_RETURN_ADDRESS_EJCI "str lr, [sp, #4]"
195 #endif
196
197 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function) \
198     asm ( \
199     ".text" "\n" \
200     ".globl " SYMBOL_STRING(function) "\n" \
201     HIDE_SYMBOL(function) "\n" \
202     INLINE_ARM_FUNCTION(function) \
203     SYMBOL_STRING(function) ":" "\n" \
204         INSTRUCTION_STORE_RETURN_ADDRESS_EJI "\n" \
205         "b " LOCAL_REFERENCE(function) "WithReturnAddress" "\n" \
206     );
207
208 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) \
209     asm ( \
210     ".text" "\n" \
211     ".globl " SYMBOL_STRING(function) "\n" \
212     HIDE_SYMBOL(function) "\n" \
213     INLINE_ARM_FUNCTION(function) \
214     SYMBOL_STRING(function) ":" "\n" \
215         INSTRUCTION_STORE_RETURN_ADDRESS_EJCI "\n" \
216         "b " LOCAL_REFERENCE(function) "WithReturnAddress" "\n" \
217     );
218
219 #elif COMPILER(GCC) && CPU(MIPS)
220
221 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function) \
222     asm( \
223     ".text" "\n" \
224     ".globl " SYMBOL_STRING(function) "\n" \
225     HIDE_SYMBOL(function) "\n" \
226     SYMBOL_STRING(function) ":" "\n" \
227     LOAD_FUNCTION_TO_T9(function##WithReturnAddress) \
228         "move $a1, $ra" "\n" \
229         "b " LOCAL_REFERENCE(function) "WithReturnAddress" "\n" \
230     );
231
232 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function) \
233     asm( \
234     ".text" "\n" \
235     ".globl " SYMBOL_STRING(function) "\n" \
236     HIDE_SYMBOL(function) "\n" \
237     SYMBOL_STRING(function) ":" "\n" \
238     LOAD_FUNCTION_TO_T9(function##WithReturnAddress) \
239         "move $a3, $ra" "\n" \
240         "b " LOCAL_REFERENCE(function) "WithReturnAddress" "\n" \
241     );
242
243 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function) \
244     asm( \
245     ".text" "\n" \
246     ".globl " SYMBOL_STRING(function) "\n" \
247     HIDE_SYMBOL(function) "\n" \
248     SYMBOL_STRING(function) ":" "\n" \
249     LOAD_FUNCTION_TO_T9(function##WithReturnAddress) \
250         "sw $ra, 20($sp)" "\n" \
251         "b " LOCAL_REFERENCE(function) "WithReturnAddress" "\n" \
252     );
253
254 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) \
255     asm( \
256     ".text" "\n" \
257     ".globl " SYMBOL_STRING(function) "\n" \
258     HIDE_SYMBOL(function) "\n" \
259     SYMBOL_STRING(function) ":" "\n" \
260     LOAD_FUNCTION_TO_T9(function##WithReturnAddress) \
261         "sw $ra, 24($sp)" "\n" \
262         "b " LOCAL_REFERENCE(function) "WithReturnAddress" "\n" \
263     );
264
265 #elif COMPILER(GCC) && CPU(SH4)
266
267 #define SH4_SCRATCH_REGISTER "r11"
268
269 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function) \
270     asm( \
271     ".text" "\n" \
272     ".globl " SYMBOL_STRING(function) "\n" \
273     HIDE_SYMBOL(function) "\n" \
274     SYMBOL_STRING(function) ":" "\n" \
275         "sts pr, r5" "\n" \
276         "bra " LOCAL_REFERENCE(function) "WithReturnAddress" "\n" \
277         "nop" "\n" \
278     );
279
280 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function) \
281     asm( \
282     ".text" "\n" \
283     ".globl " SYMBOL_STRING(function) "\n" \
284     HIDE_SYMBOL(function) "\n" \
285     SYMBOL_STRING(function) ":" "\n" \
286         "sts pr, r7" "\n" \
287         "mov.l 2f, " SH4_SCRATCH_REGISTER "\n" \
288         "braf " SH4_SCRATCH_REGISTER "\n" \
289         "nop" "\n" \
290         "1: .balign 4" "\n" \
291         "2: .long " LOCAL_REFERENCE(function) "WithReturnAddress-1b" "\n" \
292     );
293
294 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, offset, scratch) \
295     asm( \
296     ".text" "\n" \
297     ".globl " SYMBOL_STRING(function) "\n" \
298     HIDE_SYMBOL(function) "\n" \
299     SYMBOL_STRING(function) ":" "\n" \
300         "sts pr, " scratch "\n" \
301         "mov.l " scratch ", @(" STRINGIZE(offset) ", r15)" "\n" \
302         "mov.l 2f, " scratch "\n" \
303         "braf " scratch "\n" \
304         "nop" "\n" \
305         "1: .balign 4" "\n" \
306         "2: .long " LOCAL_REFERENCE(function) "WithReturnAddress-1b" "\n" \
307     );
308
309 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function)  FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, 0, SH4_SCRATCH_REGISTER)
310 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, 4, SH4_SCRATCH_REGISTER)
311
312 #endif
313
314 #define P_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function) \
315 void* DFG_OPERATION function##WithReturnAddress(ExecState*, ReturnAddressPtr) REFERENCED_FROM_ASM WTF_INTERNAL; \
316 FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function)
317
318 #define J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function) \
319 EncodedJSValue DFG_OPERATION function##WithReturnAddress(ExecState*, JSCell*, StringImpl*, ReturnAddressPtr) REFERENCED_FROM_ASM WTF_INTERNAL; \
320 FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function)
321
322 #define J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function) \
323 EncodedJSValue DFG_OPERATION function##WithReturnAddress(ExecState*, EncodedJSValue, StringImpl*, ReturnAddressPtr) REFERENCED_FROM_ASM WTF_INTERNAL; \
324 FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function)
325
326 #define V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) \
327 void DFG_OPERATION function##WithReturnAddress(ExecState*, EncodedJSValue, JSCell*, StringImpl*, ReturnAddressPtr) REFERENCED_FROM_ASM WTF_INTERNAL; \
328 FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function)
329
330 namespace JSC { namespace DFG {
331
332 template<bool strict>
333 static inline void putByVal(ExecState* exec, JSValue baseValue, uint32_t index, JSValue value)
334 {
335     VM& vm = exec->vm();
336     NativeCallFrameTracer tracer(&vm, exec);
337     
338     if (baseValue.isObject()) {
339         JSObject* object = asObject(baseValue);
340         if (object->canSetIndexQuickly(index)) {
341             object->setIndexQuickly(vm, index, value);
342             return;
343         }
344
345         object->methodTable()->putByIndex(object, exec, index, value, strict);
346         return;
347     }
348
349     baseValue.putByIndex(exec, index, value, strict);
350 }
351
352 template<bool strict>
353 ALWAYS_INLINE static void DFG_OPERATION operationPutByValInternal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
354 {
355     VM* vm = &exec->vm();
356     NativeCallFrameTracer tracer(vm, exec);
357
358     JSValue baseValue = JSValue::decode(encodedBase);
359     JSValue property = JSValue::decode(encodedProperty);
360     JSValue value = JSValue::decode(encodedValue);
361
362     if (LIKELY(property.isUInt32())) {
363         putByVal<strict>(exec, baseValue, property.asUInt32(), value);
364         return;
365     }
366
367     if (property.isDouble()) {
368         double propertyAsDouble = property.asDouble();
369         uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
370         if (propertyAsDouble == propertyAsUInt32) {
371             putByVal<strict>(exec, baseValue, propertyAsUInt32, value);
372             return;
373         }
374     }
375
376     if (isName(property)) {
377         PutPropertySlot slot(strict);
378         baseValue.put(exec, jsCast<NameInstance*>(property.asCell())->privateName(), value, slot);
379         return;
380     }
381
382     // Don't put to an object if toString throws an exception.
383     Identifier ident(exec, property.toString(exec)->value(exec));
384     if (!vm->exception) {
385         PutPropertySlot slot(strict);
386         baseValue.put(exec, ident, value, slot);
387     }
388 }
389
390 extern "C" {
391
392 EncodedJSValue DFG_OPERATION operationToThis(ExecState* exec, EncodedJSValue encodedOp)
393 {
394     VM* vm = &exec->vm();
395     NativeCallFrameTracer tracer(vm, exec);
396
397     return JSValue::encode(JSValue::decode(encodedOp).toThis(exec, exec->codeBlock()->isStrictMode() ? StrictMode : NotStrictMode));
398 }
399
400 JSCell* DFG_OPERATION operationCreateThis(ExecState* exec, JSObject* constructor, int32_t inlineCapacity)
401 {
402     VM* vm = &exec->vm();
403     NativeCallFrameTracer tracer(vm, exec);
404
405 #if !ASSERT_DISABLED
406     ConstructData constructData;
407     ASSERT(jsCast<JSFunction*>(constructor)->methodTable()->getConstructData(jsCast<JSFunction*>(constructor), constructData) == ConstructTypeJS);
408 #endif
409     
410     return constructEmptyObject(exec, jsCast<JSFunction*>(constructor)->allocationProfile(exec, inlineCapacity)->structure());
411 }
412
413 JSCell* DFG_OPERATION operationNewObject(ExecState* exec, Structure* structure)
414 {
415     VM* vm = &exec->vm();
416     NativeCallFrameTracer tracer(vm, exec);
417     
418     return constructEmptyObject(exec, structure);
419 }
420
421 EncodedJSValue DFG_OPERATION operationValueAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
422 {
423     VM* vm = &exec->vm();
424     NativeCallFrameTracer tracer(vm, exec);
425     
426     JSValue op1 = JSValue::decode(encodedOp1);
427     JSValue op2 = JSValue::decode(encodedOp2);
428     
429     return JSValue::encode(jsAdd(exec, op1, op2));
430 }
431
432 EncodedJSValue DFG_OPERATION operationValueAddNotNumber(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
433 {
434     VM* vm = &exec->vm();
435     NativeCallFrameTracer tracer(vm, exec);
436     
437     JSValue op1 = JSValue::decode(encodedOp1);
438     JSValue op2 = JSValue::decode(encodedOp2);
439     
440     ASSERT(!op1.isNumber() || !op2.isNumber());
441     
442     if (op1.isString() && !op2.isObject())
443         return JSValue::encode(jsString(exec, asString(op1), op2.toString(exec)));
444
445     return JSValue::encode(jsAddSlowCase(exec, op1, op2));
446 }
447
448 static inline EncodedJSValue getByVal(ExecState* exec, JSCell* base, uint32_t index)
449 {
450     VM& vm = exec->vm();
451     NativeCallFrameTracer tracer(&vm, exec);
452     
453     if (base->isObject()) {
454         JSObject* object = asObject(base);
455         if (object->canGetIndexQuickly(index))
456             return JSValue::encode(object->getIndexQuickly(index));
457     }
458
459     if (isJSString(base) && asString(base)->canGetIndex(index))
460         return JSValue::encode(asString(base)->getIndex(exec, index));
461
462     return JSValue::encode(JSValue(base).get(exec, index));
463 }
464
465 EncodedJSValue DFG_OPERATION operationGetByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty)
466 {
467     VM* vm = &exec->vm();
468     NativeCallFrameTracer tracer(vm, exec);
469     
470     JSValue baseValue = JSValue::decode(encodedBase);
471     JSValue property = JSValue::decode(encodedProperty);
472
473     if (LIKELY(baseValue.isCell())) {
474         JSCell* base = baseValue.asCell();
475
476         if (property.isUInt32()) {
477             return getByVal(exec, base, property.asUInt32());
478         } else if (property.isDouble()) {
479             double propertyAsDouble = property.asDouble();
480             uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
481             if (propertyAsUInt32 == propertyAsDouble)
482                 return getByVal(exec, base, propertyAsUInt32);
483         } else if (property.isString()) {
484             if (JSValue result = base->fastGetOwnProperty(exec, asString(property)->value(exec)))
485                 return JSValue::encode(result);
486         }
487     }
488
489     if (isName(property))
490         return JSValue::encode(baseValue.get(exec, jsCast<NameInstance*>(property.asCell())->privateName()));
491
492     Identifier ident(exec, property.toString(exec)->value(exec));
493     return JSValue::encode(baseValue.get(exec, ident));
494 }
495
496 EncodedJSValue DFG_OPERATION operationGetByValCell(ExecState* exec, JSCell* base, EncodedJSValue encodedProperty)
497 {
498     VM* vm = &exec->vm();
499     NativeCallFrameTracer tracer(vm, exec);
500     
501     JSValue property = JSValue::decode(encodedProperty);
502
503     if (property.isUInt32())
504         return getByVal(exec, base, property.asUInt32());
505     if (property.isDouble()) {
506         double propertyAsDouble = property.asDouble();
507         uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
508         if (propertyAsUInt32 == propertyAsDouble)
509             return getByVal(exec, base, propertyAsUInt32);
510     } else if (property.isString()) {
511         if (JSValue result = base->fastGetOwnProperty(exec, asString(property)->value(exec)))
512             return JSValue::encode(result);
513     }
514
515     if (isName(property))
516         return JSValue::encode(JSValue(base).get(exec, jsCast<NameInstance*>(property.asCell())->privateName()));
517
518     Identifier ident(exec, property.toString(exec)->value(exec));
519     return JSValue::encode(JSValue(base).get(exec, ident));
520 }
521
522 ALWAYS_INLINE EncodedJSValue getByValCellInt(ExecState* exec, JSCell* base, int32_t index)
523 {
524     VM* vm = &exec->vm();
525     NativeCallFrameTracer tracer(vm, exec);
526     
527     if (index < 0) {
528         // Go the slowest way possible becase negative indices don't use indexed storage.
529         return JSValue::encode(JSValue(base).get(exec, Identifier::from(exec, index)));
530     }
531
532     // Use this since we know that the value is out of bounds.
533     return JSValue::encode(JSValue(base).get(exec, index));
534 }
535
536 EncodedJSValue DFG_OPERATION operationGetByValArrayInt(ExecState* exec, JSArray* base, int32_t index)
537 {
538     return getByValCellInt(exec, base, index);
539 }
540
541 EncodedJSValue DFG_OPERATION operationGetByValStringInt(ExecState* exec, JSString* base, int32_t index)
542 {
543     return getByValCellInt(exec, base, index);
544 }
545
546 EncodedJSValue DFG_OPERATION operationGetById(ExecState* exec, EncodedJSValue base, StringImpl* uid)
547 {
548     VM* vm = &exec->vm();
549     NativeCallFrameTracer tracer(vm, exec);
550     
551     JSValue baseValue = JSValue::decode(base);
552     PropertySlot slot(baseValue);
553     Identifier ident(vm, uid);
554     return JSValue::encode(baseValue.get(exec, ident, slot));
555 }
556
557 J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(operationGetByIdBuildList);
558 EncodedJSValue DFG_OPERATION operationGetByIdBuildListWithReturnAddress(ExecState* exec, EncodedJSValue base, StringImpl* uid, ReturnAddressPtr returnAddress)
559 {
560     VM* vm = &exec->vm();
561     NativeCallFrameTracer tracer(vm, exec);
562
563     Identifier ident(vm, uid);
564     StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
565     AccessType accessType = static_cast<AccessType>(stubInfo.accessType);
566
567     JSValue baseValue = JSValue::decode(base);
568     PropertySlot slot(baseValue);
569     JSValue result = baseValue.get(exec, ident, slot);
570
571     if (accessType == static_cast<AccessType>(stubInfo.accessType))
572         dfgBuildGetByIDList(exec, baseValue, ident, slot, stubInfo);
573
574     return JSValue::encode(result);
575 }
576
577 J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(operationGetByIdOptimize);
578 EncodedJSValue DFG_OPERATION operationGetByIdOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue base, StringImpl* uid, ReturnAddressPtr returnAddress)
579 {
580     VM* vm = &exec->vm();
581     NativeCallFrameTracer tracer(vm, exec);
582
583     Identifier ident(vm, uid);
584     StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
585     AccessType accessType = static_cast<AccessType>(stubInfo.accessType);
586
587     JSValue baseValue = JSValue::decode(base);
588     PropertySlot slot(baseValue);
589     JSValue result = baseValue.get(exec, ident, slot);
590     
591     if (accessType == static_cast<AccessType>(stubInfo.accessType)) {
592         if (stubInfo.seen)
593             dfgRepatchGetByID(exec, baseValue, ident, slot, stubInfo);
594         else
595             stubInfo.seen = true;
596     }
597
598     return JSValue::encode(result);
599 }
600
601 J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(operationInOptimize);
602 EncodedJSValue DFG_OPERATION operationInOptimizeWithReturnAddress(ExecState* exec, JSCell* base, StringImpl* key, ReturnAddressPtr returnAddress)
603 {
604     VM* vm = &exec->vm();
605     NativeCallFrameTracer tracer(vm, exec);
606     
607     if (!base->isObject()) {
608         vm->exception = createInvalidParameterError(exec, "in", base);
609         return jsUndefined();
610     }
611     
612     StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
613     AccessType accessType = static_cast<AccessType>(stubInfo.accessType);
614
615     Identifier ident(vm, key);
616     PropertySlot slot(base);
617     bool result = asObject(base)->getPropertySlot(exec, ident, slot);
618     
619     RELEASE_ASSERT(accessType == stubInfo.accessType);
620     
621     if (stubInfo.seen)
622         dfgRepatchIn(exec, base, ident, result, slot, stubInfo);
623     else
624         stubInfo.seen = true;
625     
626     return JSValue::encode(jsBoolean(result));
627 }
628
629 EncodedJSValue DFG_OPERATION operationIn(ExecState* exec, JSCell* base, StringImpl* key)
630 {
631     VM* vm = &exec->vm();
632     NativeCallFrameTracer tracer(vm, exec);
633
634     if (!base->isObject()) {
635         vm->exception = createInvalidParameterError(exec, "in", base);
636         return jsUndefined();
637     }
638
639     Identifier ident(vm, key);
640     return JSValue::encode(jsBoolean(asObject(base)->hasProperty(exec, ident)));
641 }
642
643 EncodedJSValue DFG_OPERATION operationGenericIn(ExecState* exec, JSCell* base, EncodedJSValue key)
644 {
645     VM* vm = &exec->vm();
646     NativeCallFrameTracer tracer(vm, exec);
647
648     return JSValue::encode(jsBoolean(CommonSlowPaths::opIn(exec, JSValue::decode(key), base)));
649 }
650
651 EncodedJSValue DFG_OPERATION operationCallCustomGetter(ExecState* exec, JSCell* base, PropertySlot::GetValueFunc function, StringImpl* uid)
652 {
653     VM* vm = &exec->vm();
654     NativeCallFrameTracer tracer(vm, exec);
655     
656     Identifier ident(vm, uid);
657     
658     return JSValue::encode(function(exec, asObject(base), ident));
659 }
660
661 EncodedJSValue DFG_OPERATION operationCallGetter(ExecState* exec, JSCell* base, JSCell* getterSetter)
662 {
663     VM* vm = &exec->vm();
664     NativeCallFrameTracer tracer(vm, exec);
665
666     return JSValue::encode(callGetter(exec, base, getterSetter));
667 }
668
669 void DFG_OPERATION operationPutByValStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
670 {
671     VM* vm = &exec->vm();
672     NativeCallFrameTracer tracer(vm, exec);
673     
674     operationPutByValInternal<true>(exec, encodedBase, encodedProperty, encodedValue);
675 }
676
677 void DFG_OPERATION operationPutByValNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
678 {
679     VM* vm = &exec->vm();
680     NativeCallFrameTracer tracer(vm, exec);
681     
682     operationPutByValInternal<false>(exec, encodedBase, encodedProperty, encodedValue);
683 }
684
685 void DFG_OPERATION operationPutByValCellStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
686 {
687     VM* vm = &exec->vm();
688     NativeCallFrameTracer tracer(vm, exec);
689     
690     operationPutByValInternal<true>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
691 }
692
693 void DFG_OPERATION operationPutByValCellNonStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
694 {
695     VM* vm = &exec->vm();
696     NativeCallFrameTracer tracer(vm, exec);
697     
698     operationPutByValInternal<false>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
699 }
700
701 void DFG_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
702 {
703     VM* vm = &exec->vm();
704     NativeCallFrameTracer tracer(vm, exec);
705     
706     if (index >= 0) {
707         array->putByIndexInline(exec, index, JSValue::decode(encodedValue), true);
708         return;
709     }
710     
711     PutPropertySlot slot(true);
712     array->methodTable()->put(
713         array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
714 }
715
716 void DFG_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
717 {
718     VM* vm = &exec->vm();
719     NativeCallFrameTracer tracer(vm, exec);
720     
721     if (index >= 0) {
722         array->putByIndexInline(exec, index, JSValue::decode(encodedValue), false);
723         return;
724     }
725     
726     PutPropertySlot slot(false);
727     array->methodTable()->put(
728         array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
729 }
730
731 void DFG_OPERATION operationPutDoubleByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, double value)
732 {
733     VM* vm = &exec->vm();
734     NativeCallFrameTracer tracer(vm, exec);
735     
736     JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
737     
738     if (index >= 0) {
739         array->putByIndexInline(exec, index, jsValue, true);
740         return;
741     }
742     
743     PutPropertySlot slot(true);
744     array->methodTable()->put(
745         array, exec, Identifier::from(exec, index), jsValue, slot);
746 }
747
748 void DFG_OPERATION operationPutDoubleByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, double value)
749 {
750     VM* vm = &exec->vm();
751     NativeCallFrameTracer tracer(vm, exec);
752     
753     JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
754     
755     if (index >= 0) {
756         array->putByIndexInline(exec, index, jsValue, false);
757         return;
758     }
759     
760     PutPropertySlot slot(false);
761     array->methodTable()->put(
762         array, exec, Identifier::from(exec, index), jsValue, slot);
763 }
764
765 EncodedJSValue DFG_OPERATION operationArrayPush(ExecState* exec, EncodedJSValue encodedValue, JSArray* array)
766 {
767     VM* vm = &exec->vm();
768     NativeCallFrameTracer tracer(vm, exec);
769     
770     array->push(exec, JSValue::decode(encodedValue));
771     return JSValue::encode(jsNumber(array->length()));
772 }
773
774 EncodedJSValue DFG_OPERATION operationArrayPushDouble(ExecState* exec, double value, JSArray* array)
775 {
776     VM* vm = &exec->vm();
777     NativeCallFrameTracer tracer(vm, exec);
778     
779     array->push(exec, JSValue(JSValue::EncodeAsDouble, value));
780     return JSValue::encode(jsNumber(array->length()));
781 }
782
783 EncodedJSValue DFG_OPERATION operationArrayPop(ExecState* exec, JSArray* array)
784 {
785     VM* vm = &exec->vm();
786     NativeCallFrameTracer tracer(vm, exec);
787     
788     return JSValue::encode(array->pop(exec));
789 }
790         
791 EncodedJSValue DFG_OPERATION operationArrayPopAndRecoverLength(ExecState* exec, JSArray* array)
792 {
793     VM* vm = &exec->vm();
794     NativeCallFrameTracer tracer(vm, exec);
795     
796     array->butterfly()->setPublicLength(array->butterfly()->publicLength() + 1);
797     
798     return JSValue::encode(array->pop(exec));
799 }
800         
801 EncodedJSValue DFG_OPERATION operationRegExpExec(ExecState* exec, JSCell* base, JSCell* argument)
802 {
803     VM& vm = exec->vm();
804     NativeCallFrameTracer tracer(&vm, exec);
805     
806     if (!base->inherits(RegExpObject::info()))
807         return throwVMTypeError(exec);
808
809     ASSERT(argument->isString() || argument->isObject());
810     JSString* input = argument->isString() ? asString(argument) : asObject(argument)->toString(exec);
811     return JSValue::encode(asRegExpObject(base)->exec(exec, input));
812 }
813         
814 size_t DFG_OPERATION operationRegExpTest(ExecState* exec, JSCell* base, JSCell* argument)
815 {
816     VM& vm = exec->vm();
817     NativeCallFrameTracer tracer(&vm, exec);
818
819     if (!base->inherits(RegExpObject::info())) {
820         throwTypeError(exec);
821         return false;
822     }
823
824     ASSERT(argument->isString() || argument->isObject());
825     JSString* input = argument->isString() ? asString(argument) : asObject(argument)->toString(exec);
826     return asRegExpObject(base)->test(exec, input);
827 }
828         
829 void DFG_OPERATION operationPutByIdStrict(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, StringImpl* uid)
830 {
831     VM* vm = &exec->vm();
832     NativeCallFrameTracer tracer(vm, exec);
833     
834     Identifier ident(vm, uid);
835     PutPropertySlot slot(true, exec->codeBlock()->putByIdContext());
836     base->methodTable()->put(base, exec, ident, JSValue::decode(encodedValue), slot);
837 }
838
839 void DFG_OPERATION operationPutByIdNonStrict(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, StringImpl* uid)
840 {
841     VM* vm = &exec->vm();
842     NativeCallFrameTracer tracer(vm, exec);
843     
844     Identifier ident(vm, uid);
845     PutPropertySlot slot(false, exec->codeBlock()->putByIdContext());
846     base->methodTable()->put(base, exec, ident, JSValue::decode(encodedValue), slot);
847 }
848
849 void DFG_OPERATION operationPutByIdDirectStrict(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, StringImpl* uid)
850 {
851     VM* vm = &exec->vm();
852     NativeCallFrameTracer tracer(vm, exec);
853     
854     Identifier ident(vm, uid);
855     PutPropertySlot slot(true, exec->codeBlock()->putByIdContext());
856     ASSERT(base->isObject());
857     asObject(base)->putDirect(exec->vm(), ident, JSValue::decode(encodedValue), slot);
858 }
859
860 void DFG_OPERATION operationPutByIdDirectNonStrict(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, StringImpl* uid)
861 {
862     VM* vm = &exec->vm();
863     NativeCallFrameTracer tracer(vm, exec);
864     
865     Identifier ident(vm, uid);
866     PutPropertySlot slot(false, exec->codeBlock()->putByIdContext());
867     ASSERT(base->isObject());
868     asObject(base)->putDirect(exec->vm(), ident, JSValue::decode(encodedValue), slot);
869 }
870
871 V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdStrictOptimize);
872 void DFG_OPERATION operationPutByIdStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, StringImpl* uid, ReturnAddressPtr returnAddress)
873 {
874     VM* vm = &exec->vm();
875     NativeCallFrameTracer tracer(vm, exec);
876     
877     Identifier ident(vm, uid);
878     StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
879     AccessType accessType = static_cast<AccessType>(stubInfo.accessType);
880
881     JSValue value = JSValue::decode(encodedValue);
882     JSValue baseValue(base);
883     PutPropertySlot slot(true, exec->codeBlock()->putByIdContext());
884     
885     baseValue.put(exec, ident, value, slot);
886     
887     if (accessType != static_cast<AccessType>(stubInfo.accessType))
888         return;
889     
890     if (stubInfo.seen)
891         dfgRepatchPutByID(exec, baseValue, ident, slot, stubInfo, NotDirect);
892     else
893         stubInfo.seen = true;
894 }
895
896 V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdNonStrictOptimize);
897 void DFG_OPERATION operationPutByIdNonStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, StringImpl* uid, ReturnAddressPtr returnAddress)
898 {
899     VM* vm = &exec->vm();
900     NativeCallFrameTracer tracer(vm, exec);
901     
902     Identifier ident(vm, uid);
903     StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
904     AccessType accessType = static_cast<AccessType>(stubInfo.accessType);
905
906     JSValue value = JSValue::decode(encodedValue);
907     JSValue baseValue(base);
908     PutPropertySlot slot(false, exec->codeBlock()->putByIdContext());
909     
910     baseValue.put(exec, ident, value, slot);
911     
912     if (accessType != static_cast<AccessType>(stubInfo.accessType))
913         return;
914     
915     if (stubInfo.seen)
916         dfgRepatchPutByID(exec, baseValue, ident, slot, stubInfo, NotDirect);
917     else
918         stubInfo.seen = true;
919 }
920
921 V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdDirectStrictOptimize);
922 void DFG_OPERATION operationPutByIdDirectStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, StringImpl* uid, ReturnAddressPtr returnAddress)
923 {
924     VM* vm = &exec->vm();
925     NativeCallFrameTracer tracer(vm, exec);
926     
927     Identifier ident(vm, uid);
928     StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
929     AccessType accessType = static_cast<AccessType>(stubInfo.accessType);
930
931     JSValue value = JSValue::decode(encodedValue);
932     PutPropertySlot slot(true, exec->codeBlock()->putByIdContext());
933     
934     ASSERT(base->isObject());
935     asObject(base)->putDirect(exec->vm(), ident, value, slot);
936     
937     if (accessType != static_cast<AccessType>(stubInfo.accessType))
938         return;
939     
940     if (stubInfo.seen)
941         dfgRepatchPutByID(exec, base, ident, slot, stubInfo, Direct);
942     else
943         stubInfo.seen = true;
944 }
945
946 V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdDirectNonStrictOptimize);
947 void DFG_OPERATION operationPutByIdDirectNonStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, StringImpl* uid, ReturnAddressPtr returnAddress)
948 {
949     VM* vm = &exec->vm();
950     NativeCallFrameTracer tracer(vm, exec);
951     
952     Identifier ident(vm, uid);
953     StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
954     AccessType accessType = static_cast<AccessType>(stubInfo.accessType);
955
956     JSValue value = JSValue::decode(encodedValue);
957     PutPropertySlot slot(false, exec->codeBlock()->putByIdContext());
958     
959     ASSERT(base->isObject());
960     asObject(base)->putDirect(exec->vm(), ident, value, slot);
961     
962     if (accessType != static_cast<AccessType>(stubInfo.accessType))
963         return;
964     
965     if (stubInfo.seen)
966         dfgRepatchPutByID(exec, base, ident, slot, stubInfo, Direct);
967     else
968         stubInfo.seen = true;
969 }
970
971 V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdStrictBuildList);
972 void DFG_OPERATION operationPutByIdStrictBuildListWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, StringImpl* uid, ReturnAddressPtr returnAddress)
973 {
974     VM* vm = &exec->vm();
975     NativeCallFrameTracer tracer(vm, exec);
976     
977     Identifier ident(vm, uid);
978     StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
979     AccessType accessType = static_cast<AccessType>(stubInfo.accessType);
980
981     JSValue value = JSValue::decode(encodedValue);
982     JSValue baseValue(base);
983     PutPropertySlot slot(true, exec->codeBlock()->putByIdContext());
984     
985     baseValue.put(exec, ident, value, slot);
986     
987     if (accessType != static_cast<AccessType>(stubInfo.accessType))
988         return;
989     
990     dfgBuildPutByIdList(exec, baseValue, ident, slot, stubInfo, NotDirect);
991 }
992
993 V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdNonStrictBuildList);
994 void DFG_OPERATION operationPutByIdNonStrictBuildListWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, StringImpl* uid, ReturnAddressPtr returnAddress)
995 {
996     VM* vm = &exec->vm();
997     NativeCallFrameTracer tracer(vm, exec);
998     
999     Identifier ident(vm, uid);
1000     StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
1001     AccessType accessType = static_cast<AccessType>(stubInfo.accessType);
1002
1003     JSValue value = JSValue::decode(encodedValue);
1004     JSValue baseValue(base);
1005     PutPropertySlot slot(false, exec->codeBlock()->putByIdContext());
1006     
1007     baseValue.put(exec, ident, value, slot);
1008     
1009     if (accessType != static_cast<AccessType>(stubInfo.accessType))
1010         return;
1011     
1012     dfgBuildPutByIdList(exec, baseValue, ident, slot, stubInfo, NotDirect);
1013 }
1014
1015 V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdDirectStrictBuildList);
1016 void DFG_OPERATION operationPutByIdDirectStrictBuildListWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, StringImpl* uid, ReturnAddressPtr returnAddress)
1017 {
1018     VM* vm = &exec->vm();
1019     NativeCallFrameTracer tracer(vm, exec);
1020     
1021     Identifier ident(vm, uid);
1022     StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
1023     AccessType accessType = static_cast<AccessType>(stubInfo.accessType);
1024     
1025     JSValue value = JSValue::decode(encodedValue);
1026     PutPropertySlot slot(true, exec->codeBlock()->putByIdContext());
1027     
1028     ASSERT(base->isObject());
1029     asObject(base)->putDirect(exec->vm(), ident, value, slot);
1030     
1031     if (accessType != static_cast<AccessType>(stubInfo.accessType))
1032         return;
1033     
1034     dfgBuildPutByIdList(exec, base, ident, slot, stubInfo, Direct);
1035 }
1036
1037 V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdDirectNonStrictBuildList);
1038 void DFG_OPERATION operationPutByIdDirectNonStrictBuildListWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, StringImpl* uid, ReturnAddressPtr returnAddress)
1039 {
1040     VM* vm = &exec->vm();
1041     NativeCallFrameTracer tracer(vm, exec);
1042     
1043     Identifier ident(vm, uid);
1044     StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
1045     AccessType accessType = static_cast<AccessType>(stubInfo.accessType);
1046
1047     JSValue value = JSValue::decode(encodedValue);
1048     PutPropertySlot slot(false, exec->codeBlock()->putByIdContext());
1049     
1050     ASSERT(base->isObject());
1051     asObject(base)->putDirect(exec->vm(), ident, value, slot);
1052     
1053     if (accessType != static_cast<AccessType>(stubInfo.accessType))
1054         return;
1055     
1056     dfgBuildPutByIdList(exec, base, ident, slot, stubInfo, Direct);
1057 }
1058
1059 size_t DFG_OPERATION operationCompareLess(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
1060 {
1061     VM* vm = &exec->vm();
1062     NativeCallFrameTracer tracer(vm, exec);
1063     
1064     return jsLess<true>(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
1065 }
1066
1067 size_t DFG_OPERATION operationCompareLessEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
1068 {
1069     VM* vm = &exec->vm();
1070     NativeCallFrameTracer tracer(vm, exec);
1071     
1072     return jsLessEq<true>(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
1073 }
1074
1075 size_t DFG_OPERATION operationCompareGreater(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
1076 {
1077     VM* vm = &exec->vm();
1078     NativeCallFrameTracer tracer(vm, exec);
1079     
1080     return jsLess<false>(exec, JSValue::decode(encodedOp2), JSValue::decode(encodedOp1));
1081 }
1082
1083 size_t DFG_OPERATION operationCompareGreaterEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
1084 {
1085     VM* vm = &exec->vm();
1086     NativeCallFrameTracer tracer(vm, exec);
1087     
1088     return jsLessEq<false>(exec, JSValue::decode(encodedOp2), JSValue::decode(encodedOp1));
1089 }
1090
1091 size_t DFG_OPERATION operationCompareEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
1092 {
1093     VM* vm = &exec->vm();
1094     NativeCallFrameTracer tracer(vm, exec);
1095     
1096     return JSValue::equalSlowCaseInline(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
1097 }
1098
1099 #if USE(JSVALUE64)
1100 EncodedJSValue DFG_OPERATION operationCompareStringEq(ExecState* exec, JSCell* left, JSCell* right)
1101 #else
1102 size_t DFG_OPERATION operationCompareStringEq(ExecState* exec, JSCell* left, JSCell* right)
1103 #endif
1104 {
1105     VM* vm = &exec->vm();
1106     NativeCallFrameTracer tracer(vm, exec);
1107     
1108     bool result = asString(left)->value(exec) == asString(right)->value(exec);
1109 #if USE(JSVALUE64)
1110     return JSValue::encode(jsBoolean(result));
1111 #else
1112     return result;
1113 #endif
1114 }
1115
1116 size_t DFG_OPERATION operationCompareStrictEqCell(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
1117 {
1118     VM* vm = &exec->vm();
1119     NativeCallFrameTracer tracer(vm, exec);
1120     
1121     JSValue op1 = JSValue::decode(encodedOp1);
1122     JSValue op2 = JSValue::decode(encodedOp2);
1123     
1124     ASSERT(op1.isCell());
1125     ASSERT(op2.isCell());
1126     
1127     return JSValue::strictEqualSlowCaseInline(exec, op1, op2);
1128 }
1129
1130 size_t DFG_OPERATION operationCompareStrictEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
1131 {
1132     VM* vm = &exec->vm();
1133     NativeCallFrameTracer tracer(vm, exec);
1134
1135     JSValue src1 = JSValue::decode(encodedOp1);
1136     JSValue src2 = JSValue::decode(encodedOp2);
1137     
1138     return JSValue::strictEqual(exec, src1, src2);
1139 }
1140
1141 static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializationKind kind)
1142 {
1143     ExecState* exec = execCallee->callerFrame();
1144     VM* vm = &exec->vm();
1145
1146     execCallee->setScope(exec->scope());
1147     execCallee->setCodeBlock(0);
1148
1149     if (kind == CodeForCall) {
1150         CallData callData;
1151         CallType callType = getCallData(callee, callData);
1152     
1153         ASSERT(callType != CallTypeJS);
1154     
1155         if (callType == CallTypeHost) {
1156             NativeCallFrameTracer tracer(vm, execCallee);
1157             execCallee->setCallee(asObject(callee));
1158             vm->hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
1159             if (vm->exception)
1160                 return vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
1161
1162             return reinterpret_cast<void*>(getHostCallReturnValue);
1163         }
1164     
1165         ASSERT(callType == CallTypeNone);
1166         exec->vm().exception = createNotAFunctionError(exec, callee);
1167         return vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
1168     }
1169
1170     ASSERT(kind == CodeForConstruct);
1171     
1172     ConstructData constructData;
1173     ConstructType constructType = getConstructData(callee, constructData);
1174     
1175     ASSERT(constructType != ConstructTypeJS);
1176     
1177     if (constructType == ConstructTypeHost) {
1178         NativeCallFrameTracer tracer(vm, execCallee);
1179         execCallee->setCallee(asObject(callee));
1180         vm->hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee));
1181         if (vm->exception)
1182             return vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
1183
1184         return reinterpret_cast<void*>(getHostCallReturnValue);
1185     }
1186     
1187     ASSERT(constructType == ConstructTypeNone);
1188     exec->vm().exception = createNotAConstructorError(exec, callee);
1189     return vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
1190 }
1191
1192 inline char* linkFor(ExecState* execCallee, CodeSpecializationKind kind)
1193 {
1194     ExecState* exec = execCallee->callerFrame();
1195     VM* vm = &exec->vm();
1196     NativeCallFrameTracer tracer(vm, exec);
1197     
1198     JSValue calleeAsValue = execCallee->calleeAsValue();
1199     JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
1200     if (!calleeAsFunctionCell)
1201         return reinterpret_cast<char*>(handleHostCall(execCallee, calleeAsValue, kind));
1202
1203     JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell);
1204     execCallee->setScope(callee->scopeUnchecked());
1205     ExecutableBase* executable = callee->executable();
1206
1207     MacroAssemblerCodePtr codePtr;
1208     CodeBlock* codeBlock = 0;
1209     if (executable->isHostFunction())
1210         codePtr = executable->generatedJITCodeFor(kind)->addressForCall();
1211     else {
1212         FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
1213         JSObject* error = functionExecutable->compileFor(execCallee, callee->scope(), kind);
1214         if (error) {
1215             vm->exception = createStackOverflowError(exec);
1216             return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
1217         }
1218         codeBlock = &functionExecutable->generatedBytecodeFor(kind);
1219         if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()))
1220             codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
1221         else
1222             codePtr = functionExecutable->generatedJITCodeFor(kind)->addressForCall();
1223     }
1224     CallLinkInfo& callLinkInfo = exec->codeBlock()->getCallLinkInfo(execCallee->returnPC());
1225     if (!callLinkInfo.seenOnce())
1226         callLinkInfo.setSeen();
1227     else
1228         dfgLinkFor(execCallee, callLinkInfo, codeBlock, callee, codePtr, kind);
1229     return reinterpret_cast<char*>(codePtr.executableAddress());
1230 }
1231
1232 char* DFG_OPERATION operationLinkCall(ExecState* execCallee)
1233 {
1234     return linkFor(execCallee, CodeForCall);
1235 }
1236
1237 char* DFG_OPERATION operationLinkConstruct(ExecState* execCallee)
1238 {
1239     return linkFor(execCallee, CodeForConstruct);
1240 }
1241
1242 inline char* virtualForWithFunction(ExecState* execCallee, CodeSpecializationKind kind, JSCell*& calleeAsFunctionCell)
1243 {
1244     ExecState* exec = execCallee->callerFrame();
1245     VM* vm = &exec->vm();
1246     NativeCallFrameTracer tracer(vm, exec);
1247
1248     JSValue calleeAsValue = execCallee->calleeAsValue();
1249     calleeAsFunctionCell = getJSFunction(calleeAsValue);
1250     if (UNLIKELY(!calleeAsFunctionCell))
1251         return reinterpret_cast<char*>(handleHostCall(execCallee, calleeAsValue, kind));
1252     
1253     JSFunction* function = jsCast<JSFunction*>(calleeAsFunctionCell);
1254     execCallee->setScope(function->scopeUnchecked());
1255     ExecutableBase* executable = function->executable();
1256     if (UNLIKELY(!executable->hasJITCodeFor(kind))) {
1257         FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
1258         JSObject* error = functionExecutable->compileFor(execCallee, function->scope(), kind);
1259         if (error) {
1260             exec->vm().exception = error;
1261             return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
1262         }
1263     }
1264     return reinterpret_cast<char*>(executable->generatedJITCodeWithArityCheckFor(kind).executableAddress());
1265 }
1266
1267 inline char* virtualFor(ExecState* execCallee, CodeSpecializationKind kind)
1268 {
1269     JSCell* calleeAsFunctionCellIgnored;
1270     return virtualForWithFunction(execCallee, kind, calleeAsFunctionCellIgnored);
1271 }
1272
1273 static bool attemptToOptimizeClosureCall(ExecState* execCallee, JSCell* calleeAsFunctionCell, CallLinkInfo& callLinkInfo)
1274 {
1275     if (!calleeAsFunctionCell)
1276         return false;
1277     
1278     JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell);
1279     JSFunction* oldCallee = callLinkInfo.callee.get();
1280     
1281     if (!oldCallee
1282         || oldCallee->structure() != callee->structure()
1283         || oldCallee->executable() != callee->executable())
1284         return false;
1285     
1286     ASSERT(callee->executable()->hasJITCodeForCall());
1287     MacroAssemblerCodePtr codePtr = callee->executable()->generatedJITCodeForCall()->addressForCall();
1288     
1289     CodeBlock* codeBlock;
1290     if (callee->executable()->isHostFunction())
1291         codeBlock = 0;
1292     else {
1293         codeBlock = &jsCast<FunctionExecutable*>(callee->executable())->generatedBytecodeForCall();
1294         if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()))
1295             return false;
1296     }
1297     
1298     dfgLinkClosureCall(
1299         execCallee, callLinkInfo, codeBlock,
1300         callee->structure(), callee->executable(), codePtr);
1301     
1302     return true;
1303 }
1304
1305 char* DFG_OPERATION operationLinkClosureCall(ExecState* execCallee)
1306 {
1307     JSCell* calleeAsFunctionCell;
1308     char* result = virtualForWithFunction(execCallee, CodeForCall, calleeAsFunctionCell);
1309     CallLinkInfo& callLinkInfo = execCallee->callerFrame()->codeBlock()->getCallLinkInfo(execCallee->returnPC());
1310
1311     if (!attemptToOptimizeClosureCall(execCallee, calleeAsFunctionCell, callLinkInfo))
1312         dfgLinkSlowFor(execCallee, callLinkInfo, CodeForCall);
1313     
1314     return result;
1315 }
1316
1317 char* DFG_OPERATION operationVirtualCall(ExecState* execCallee)
1318 {    
1319     return virtualFor(execCallee, CodeForCall);
1320 }
1321
1322 char* DFG_OPERATION operationVirtualConstruct(ExecState* execCallee)
1323 {
1324     return virtualFor(execCallee, CodeForConstruct);
1325 }
1326
1327 EncodedJSValue DFG_OPERATION operationToPrimitive(ExecState* exec, EncodedJSValue value)
1328 {
1329     VM* vm = &exec->vm();
1330     NativeCallFrameTracer tracer(vm, exec);
1331     
1332     return JSValue::encode(JSValue::decode(value).toPrimitive(exec));
1333 }
1334
1335 char* DFG_OPERATION operationNewArray(ExecState* exec, Structure* arrayStructure, void* buffer, size_t size)
1336 {
1337     VM* vm = &exec->vm();
1338     NativeCallFrameTracer tracer(vm, exec);
1339     
1340     return bitwise_cast<char*>(constructArray(exec, arrayStructure, static_cast<JSValue*>(buffer), size));
1341 }
1342
1343 char* DFG_OPERATION operationNewEmptyArray(ExecState* exec, Structure* arrayStructure)
1344 {
1345     VM* vm = &exec->vm();
1346     NativeCallFrameTracer tracer(vm, exec);
1347     
1348     return bitwise_cast<char*>(JSArray::create(*vm, arrayStructure));
1349 }
1350
1351 char* DFG_OPERATION operationNewArrayWithSize(ExecState* exec, Structure* arrayStructure, int32_t size)
1352 {
1353     VM* vm = &exec->vm();
1354     NativeCallFrameTracer tracer(vm, exec);
1355
1356     if (UNLIKELY(size < 0))
1357         return bitwise_cast<char*>(throwError(exec, createRangeError(exec, ASCIILiteral("Array size is not a small enough positive integer."))));
1358
1359     return bitwise_cast<char*>(JSArray::create(*vm, arrayStructure, size));
1360 }
1361
1362 char* DFG_OPERATION operationNewArrayBuffer(ExecState* exec, Structure* arrayStructure, size_t start, size_t size)
1363 {
1364     VM& vm = exec->vm();
1365     NativeCallFrameTracer tracer(&vm, exec);
1366     return bitwise_cast<char*>(constructArray(exec, arrayStructure, exec->codeBlock()->constantBuffer(start), size));
1367 }
1368
1369 EncodedJSValue DFG_OPERATION operationNewRegexp(ExecState* exec, void* regexpPtr)
1370 {
1371     VM& vm = exec->vm();
1372     NativeCallFrameTracer tracer(&vm, exec);
1373     RegExp* regexp = static_cast<RegExp*>(regexpPtr);
1374     if (!regexp->isValid()) {
1375         throwError(exec, createSyntaxError(exec, "Invalid flags supplied to RegExp constructor."));
1376         return JSValue::encode(jsUndefined());
1377     }
1378     
1379     return JSValue::encode(RegExpObject::create(exec->vm(), exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->regExpStructure(), regexp));
1380 }
1381
1382 JSCell* DFG_OPERATION operationCreateActivation(ExecState* exec)
1383 {
1384     VM& vm = exec->vm();
1385     NativeCallFrameTracer tracer(&vm, exec);
1386     JSActivation* activation = JSActivation::create(vm, exec, exec->codeBlock());
1387     exec->setScope(activation);
1388     return activation;
1389 }
1390
1391 JSCell* DFG_OPERATION operationCreateArguments(ExecState* exec)
1392 {
1393     VM& vm = exec->vm();
1394     NativeCallFrameTracer tracer(&vm, exec);
1395     // NB: This needs to be exceedingly careful with top call frame tracking, since it
1396     // may be called from OSR exit, while the state of the call stack is bizarre.
1397     Arguments* result = Arguments::create(vm, exec);
1398     ASSERT(!vm.exception);
1399     return result;
1400 }
1401
1402 JSCell* DFG_OPERATION operationCreateInlinedArguments(
1403     ExecState* exec, InlineCallFrame* inlineCallFrame)
1404 {
1405     VM& vm = exec->vm();
1406     NativeCallFrameTracer tracer(&vm, exec);
1407     // NB: This needs to be exceedingly careful with top call frame tracking, since it
1408     // may be called from OSR exit, while the state of the call stack is bizarre.
1409     Arguments* result = Arguments::create(vm, exec, inlineCallFrame);
1410     ASSERT(!vm.exception);
1411     return result;
1412 }
1413
1414 void DFG_OPERATION operationTearOffArguments(ExecState* exec, JSCell* argumentsCell, JSCell* activationCell)
1415 {
1416     ASSERT(exec->codeBlock()->usesArguments());
1417     if (activationCell) {
1418         jsCast<Arguments*>(argumentsCell)->didTearOffActivation(exec, jsCast<JSActivation*>(activationCell));
1419         return;
1420     }
1421     jsCast<Arguments*>(argumentsCell)->tearOff(exec);
1422 }
1423
1424 void DFG_OPERATION operationTearOffInlinedArguments(
1425     ExecState* exec, JSCell* argumentsCell, JSCell* activationCell, InlineCallFrame* inlineCallFrame)
1426 {
1427     ASSERT_UNUSED(activationCell, !activationCell); // Currently, we don't inline functions with activations.
1428     jsCast<Arguments*>(argumentsCell)->tearOff(exec, inlineCallFrame);
1429 }
1430
1431 EncodedJSValue DFG_OPERATION operationGetArgumentsLength(ExecState* exec, int32_t argumentsRegister)
1432 {
1433     VM& vm = exec->vm();
1434     NativeCallFrameTracer tracer(&vm, exec);
1435     // Here we can assume that the argumernts were created. Because otherwise the JIT code would
1436     // have not made this call.
1437     Identifier ident(&vm, "length");
1438     JSValue baseValue = exec->uncheckedR(argumentsRegister).jsValue();
1439     PropertySlot slot(baseValue);
1440     return JSValue::encode(baseValue.get(exec, ident, slot));
1441 }
1442
1443 EncodedJSValue DFG_OPERATION operationGetArgumentByVal(ExecState* exec, int32_t argumentsRegister, int32_t index)
1444 {
1445     VM& vm = exec->vm();
1446     NativeCallFrameTracer tracer(&vm, exec);
1447
1448     JSValue argumentsValue = exec->uncheckedR(argumentsRegister).jsValue();
1449     
1450     // If there are no arguments, and we're accessing out of bounds, then we have to create the
1451     // arguments in case someone has installed a getter on a numeric property.
1452     if (!argumentsValue)
1453         exec->uncheckedR(argumentsRegister) = argumentsValue = Arguments::create(exec->vm(), exec);
1454     
1455     return JSValue::encode(argumentsValue.get(exec, index));
1456 }
1457
1458 EncodedJSValue DFG_OPERATION operationGetInlinedArgumentByVal(
1459     ExecState* exec, int32_t argumentsRegister, InlineCallFrame* inlineCallFrame, int32_t index)
1460 {
1461     VM& vm = exec->vm();
1462     NativeCallFrameTracer tracer(&vm, exec);
1463
1464     JSValue argumentsValue = exec->uncheckedR(argumentsRegister).jsValue();
1465     
1466     // If there are no arguments, and we're accessing out of bounds, then we have to create the
1467     // arguments in case someone has installed a getter on a numeric property.
1468     if (!argumentsValue) {
1469         exec->uncheckedR(argumentsRegister) = argumentsValue =
1470             Arguments::create(exec->vm(), exec, inlineCallFrame);
1471     }
1472     
1473     return JSValue::encode(argumentsValue.get(exec, index));
1474 }
1475
1476 JSCell* DFG_OPERATION operationNewFunctionNoCheck(ExecState* exec, JSCell* functionExecutable)
1477 {
1478     ASSERT(functionExecutable->inherits(FunctionExecutable::info()));
1479     VM& vm = exec->vm();
1480     NativeCallFrameTracer tracer(&vm, exec);
1481     return JSFunction::create(exec, static_cast<FunctionExecutable*>(functionExecutable), exec->scope());
1482 }
1483
1484 EncodedJSValue DFG_OPERATION operationNewFunction(ExecState* exec, JSCell* functionExecutable)
1485 {
1486     ASSERT(functionExecutable->inherits(FunctionExecutable::info()));
1487     VM& vm = exec->vm();
1488     NativeCallFrameTracer tracer(&vm, exec);
1489     return JSValue::encode(JSFunction::create(exec, static_cast<FunctionExecutable*>(functionExecutable), exec->scope()));
1490 }
1491
1492 JSCell* DFG_OPERATION operationNewFunctionExpression(ExecState* exec, JSCell* functionExecutableAsCell)
1493 {
1494     ASSERT(functionExecutableAsCell->inherits(FunctionExecutable::info()));
1495
1496     VM& vm = exec->vm();
1497     NativeCallFrameTracer tracer(&vm, exec);
1498
1499     FunctionExecutable* functionExecutable =
1500         static_cast<FunctionExecutable*>(functionExecutableAsCell);
1501     return JSFunction::create(exec, functionExecutable, exec->scope());
1502 }
1503
1504 size_t DFG_OPERATION operationIsObject(ExecState* exec, EncodedJSValue value)
1505 {
1506     return jsIsObjectType(exec, JSValue::decode(value));
1507 }
1508
1509 size_t DFG_OPERATION operationIsFunction(EncodedJSValue value)
1510 {
1511     return jsIsFunctionType(JSValue::decode(value));
1512 }
1513
1514 JSCell* DFG_OPERATION operationTypeOf(ExecState* exec, JSCell* value)
1515 {
1516     return jsTypeStringForValue(exec, JSValue(value)).asCell();
1517 }
1518
1519 void DFG_OPERATION operationReallocateStorageAndFinishPut(ExecState* exec, JSObject* base, Structure* structure, PropertyOffset offset, EncodedJSValue value)
1520 {
1521     VM& vm = exec->vm();
1522     NativeCallFrameTracer tracer(&vm, exec);
1523
1524     ASSERT(structure->outOfLineCapacity() > base->structure()->outOfLineCapacity());
1525     ASSERT(!vm.heap.storageAllocator().fastPathShouldSucceed(structure->outOfLineCapacity() * sizeof(JSValue)));
1526     base->setStructureAndReallocateStorageIfNecessary(vm, structure);
1527     base->putDirect(vm, offset, JSValue::decode(value));
1528 }
1529
1530 char* DFG_OPERATION operationAllocatePropertyStorageWithInitialCapacity(ExecState* exec)
1531 {
1532     VM& vm = exec->vm();
1533     NativeCallFrameTracer tracer(&vm, exec);
1534
1535     return reinterpret_cast<char*>(
1536         Butterfly::createUninitialized(vm, 0, 0, initialOutOfLineCapacity, false, 0));
1537 }
1538
1539 char* DFG_OPERATION operationAllocatePropertyStorage(ExecState* exec, size_t newSize)
1540 {
1541     VM& vm = exec->vm();
1542     NativeCallFrameTracer tracer(&vm, exec);
1543
1544     return reinterpret_cast<char*>(
1545         Butterfly::createUninitialized(vm, 0, 0, newSize, false, 0));
1546 }
1547
1548 char* DFG_OPERATION operationReallocateButterflyToHavePropertyStorageWithInitialCapacity(ExecState* exec, JSObject* object)
1549 {
1550     VM& vm = exec->vm();
1551     NativeCallFrameTracer tracer(&vm, exec);
1552
1553     ASSERT(!object->structure()->outOfLineCapacity());
1554     Butterfly* result = object->growOutOfLineStorage(vm, 0, initialOutOfLineCapacity);
1555     object->setButterflyWithoutChangingStructure(result);
1556     return reinterpret_cast<char*>(result);
1557 }
1558
1559 char* DFG_OPERATION operationReallocateButterflyToGrowPropertyStorage(ExecState* exec, JSObject* object, size_t newSize)
1560 {
1561     VM& vm = exec->vm();
1562     NativeCallFrameTracer tracer(&vm, exec);
1563
1564     Butterfly* result = object->growOutOfLineStorage(vm, object->structure()->outOfLineCapacity(), newSize);
1565     object->setButterflyWithoutChangingStructure(result);
1566     return reinterpret_cast<char*>(result);
1567 }
1568
1569 char* DFG_OPERATION operationEnsureInt32(ExecState* exec, JSCell* cell)
1570 {
1571     VM& vm = exec->vm();
1572     NativeCallFrameTracer tracer(&vm, exec);
1573     
1574     if (!cell->isObject())
1575         return 0;
1576     
1577     return reinterpret_cast<char*>(asObject(cell)->ensureInt32(vm).data());
1578 }
1579
1580 char* DFG_OPERATION operationEnsureDouble(ExecState* exec, JSCell* cell)
1581 {
1582     VM& vm = exec->vm();
1583     NativeCallFrameTracer tracer(&vm, exec);
1584     
1585     if (!cell->isObject())
1586         return 0;
1587     
1588     return reinterpret_cast<char*>(asObject(cell)->ensureDouble(vm).data());
1589 }
1590
1591 char* DFG_OPERATION operationEnsureContiguous(ExecState* exec, JSCell* cell)
1592 {
1593     VM& vm = exec->vm();
1594     NativeCallFrameTracer tracer(&vm, exec);
1595     
1596     if (!cell->isObject())
1597         return 0;
1598     
1599     return reinterpret_cast<char*>(asObject(cell)->ensureContiguous(vm).data());
1600 }
1601
1602 char* DFG_OPERATION operationRageEnsureContiguous(ExecState* exec, JSCell* cell)
1603 {
1604     VM& vm = exec->vm();
1605     NativeCallFrameTracer tracer(&vm, exec);
1606     
1607     if (!cell->isObject())
1608         return 0;
1609     
1610     return reinterpret_cast<char*>(asObject(cell)->rageEnsureContiguous(vm).data());
1611 }
1612
1613 char* DFG_OPERATION operationEnsureArrayStorage(ExecState* exec, JSCell* cell)
1614 {
1615     VM& vm = exec->vm();
1616     NativeCallFrameTracer tracer(&vm, exec);
1617     
1618     if (!cell->isObject())
1619         return 0;
1620
1621     return reinterpret_cast<char*>(asObject(cell)->ensureArrayStorage(vm));
1622 }
1623
1624 StringImpl* DFG_OPERATION operationResolveRope(ExecState* exec, JSString* string)
1625 {
1626     VM& vm = exec->vm();
1627     NativeCallFrameTracer tracer(&vm, exec);
1628
1629     return string->value(exec).impl();
1630 }
1631
1632 JSString* DFG_OPERATION operationSingleCharacterString(ExecState* exec, int32_t character)
1633 {
1634     VM& vm = exec->vm();
1635     NativeCallFrameTracer tracer(&vm, exec);
1636     
1637     return jsSingleCharacterString(exec, static_cast<UChar>(character));
1638 }
1639
1640 JSCell* DFG_OPERATION operationNewStringObject(ExecState* exec, JSString* string, Structure* structure)
1641 {
1642     VM& vm = exec->vm();
1643     NativeCallFrameTracer tracer(&vm, exec);
1644     
1645     return StringObject::create(exec, structure, string);
1646 }
1647
1648 JSCell* DFG_OPERATION operationToStringOnCell(ExecState* exec, JSCell* cell)
1649 {
1650     VM& vm = exec->vm();
1651     NativeCallFrameTracer tracer(&vm, exec);
1652     
1653     return JSValue(cell).toString(exec);
1654 }
1655
1656 JSCell* DFG_OPERATION operationToString(ExecState* exec, EncodedJSValue value)
1657 {
1658     VM& vm = exec->vm();
1659     NativeCallFrameTracer tracer(&vm, exec);
1660
1661     return JSValue::decode(value).toString(exec);
1662 }
1663
1664 JSCell* DFG_OPERATION operationMakeRope2(ExecState* exec, JSString* left, JSString* right)
1665 {
1666     VM& vm = exec->vm();
1667     NativeCallFrameTracer tracer(&vm, exec);
1668
1669     return JSRopeString::create(vm, left, right);
1670 }
1671
1672 JSCell* DFG_OPERATION operationMakeRope3(ExecState* exec, JSString* a, JSString* b, JSString* c)
1673 {
1674     VM& vm = exec->vm();
1675     NativeCallFrameTracer tracer(&vm, exec);
1676
1677     return JSRopeString::create(vm, a, b, c);
1678 }
1679
1680 char* DFG_OPERATION operationFindSwitchImmTargetForDouble(
1681     ExecState* exec, EncodedJSValue encodedValue, size_t tableIndex)
1682 {
1683     CodeBlock* codeBlock = exec->codeBlock();
1684     SimpleJumpTable& table = codeBlock->switchJumpTable(tableIndex);
1685     JSValue value = JSValue::decode(encodedValue);
1686     ASSERT(value.isDouble());
1687     double asDouble = value.asDouble();
1688     int32_t asInt32 = static_cast<int32_t>(asDouble);
1689     if (asDouble == asInt32)
1690         return static_cast<char*>(table.ctiForValue(asInt32).executableAddress());
1691     return static_cast<char*>(table.ctiDefault.executableAddress());
1692 }
1693
1694 char* DFG_OPERATION operationSwitchString(ExecState* exec, size_t tableIndex, JSString* string)
1695 {
1696     VM& vm = exec->vm();
1697     NativeCallFrameTracer tracer(&vm, exec);
1698
1699     return static_cast<char*>(exec->codeBlock()->stringSwitchJumpTable(tableIndex).ctiForValue(string->value(exec).impl()).executableAddress());
1700 }
1701
1702 double DFG_OPERATION operationFModOnInts(int32_t a, int32_t b)
1703 {
1704     return fmod(a, b);
1705 }
1706
1707 JSCell* DFG_OPERATION operationStringFromCharCode(ExecState* exec, int32_t op1)
1708 {
1709     VM* vm = &exec->vm();
1710     NativeCallFrameTracer tracer(vm, exec);
1711     return JSC::stringFromCharCode(exec, op1);
1712 }
1713
1714 DFGHandlerEncoded DFG_OPERATION lookupExceptionHandler(ExecState* exec, uint32_t callIndex)
1715 {
1716     VM* vm = &exec->vm();
1717     NativeCallFrameTracer tracer(vm, exec);
1718
1719     JSValue exceptionValue = exec->exception();
1720     ASSERT(exceptionValue);
1721     
1722     unsigned vPCIndex = exec->codeBlock()->bytecodeOffsetForCallAtIndex(callIndex);
1723     ExceptionHandler handler = genericThrow(vm, exec, exceptionValue, vPCIndex);
1724     ASSERT(handler.catchRoutine);
1725     return dfgHandlerEncoded(handler.callFrame, handler.catchRoutine);
1726 }
1727
1728 DFGHandlerEncoded DFG_OPERATION lookupExceptionHandlerInStub(ExecState* exec, StructureStubInfo* stubInfo)
1729 {
1730     VM* vm = &exec->vm();
1731     NativeCallFrameTracer tracer(vm, exec);
1732
1733     JSValue exceptionValue = exec->exception();
1734     ASSERT(exceptionValue);
1735     
1736     CodeOrigin codeOrigin = stubInfo->codeOrigin;
1737     while (codeOrigin.inlineCallFrame)
1738         codeOrigin = codeOrigin.inlineCallFrame->caller;
1739     
1740     ExceptionHandler handler = genericThrow(vm, exec, exceptionValue, codeOrigin.bytecodeIndex);
1741     ASSERT(handler.catchRoutine);
1742     return dfgHandlerEncoded(handler.callFrame, handler.catchRoutine);
1743 }
1744
1745 size_t DFG_OPERATION dfgConvertJSValueToInt32(ExecState* exec, EncodedJSValue value)
1746 {
1747     VM* vm = &exec->vm();
1748     NativeCallFrameTracer tracer(vm, exec);
1749     
1750     // toInt32/toUInt32 return the same value; we want the value zero extended to fill the register.
1751     return JSValue::decode(value).toUInt32(exec);
1752 }
1753
1754 size_t DFG_OPERATION dfgConvertJSValueToBoolean(ExecState* exec, EncodedJSValue encodedOp)
1755 {
1756     VM* vm = &exec->vm();
1757     NativeCallFrameTracer tracer(vm, exec);
1758     
1759     return JSValue::decode(encodedOp).toBoolean(exec);
1760 }
1761
1762 void DFG_OPERATION debugOperationPrintSpeculationFailure(ExecState* exec, void* debugInfoRaw, void* scratch)
1763 {
1764     VM* vm = &exec->vm();
1765     NativeCallFrameTracer tracer(vm, exec);
1766     
1767     SpeculationFailureDebugInfo* debugInfo = static_cast<SpeculationFailureDebugInfo*>(debugInfoRaw);
1768     CodeBlock* codeBlock = debugInfo->codeBlock;
1769     CodeBlock* alternative = codeBlock->alternative();
1770     dataLog(
1771         "Speculation failure in ", *codeBlock, " with ");
1772     if (alternative) {
1773         dataLog(
1774             "executeCounter = ", alternative->jitExecuteCounter(),
1775             ", reoptimizationRetryCounter = ", alternative->reoptimizationRetryCounter(),
1776             ", optimizationDelayCounter = ", alternative->optimizationDelayCounter());
1777     } else
1778         dataLog("no alternative code block (i.e. we've been jettisoned)");
1779     dataLog(", osrExitCounter = ", codeBlock->osrExitCounter(), "\n");
1780     dataLog("    GPRs at time of exit:");
1781     char* scratchPointer = static_cast<char*>(scratch);
1782     for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i) {
1783         GPRReg gpr = GPRInfo::toRegister(i);
1784         dataLog(" ", GPRInfo::debugName(gpr), ":", RawPointer(*reinterpret_cast_ptr<void**>(scratchPointer)));
1785         scratchPointer += sizeof(EncodedJSValue);
1786     }
1787     dataLog("\n");
1788     dataLog("    FPRs at time of exit:");
1789     for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) {
1790         FPRReg fpr = FPRInfo::toRegister(i);
1791         dataLog(" ", FPRInfo::debugName(fpr), ":");
1792         uint64_t bits = *reinterpret_cast_ptr<uint64_t*>(scratchPointer);
1793         double value = *reinterpret_cast_ptr<double*>(scratchPointer);
1794         dataLogF("%llx:%lf", static_cast<long long>(bits), value);
1795         scratchPointer += sizeof(EncodedJSValue);
1796     }
1797     dataLog("\n");
1798 }
1799
1800 extern "C" void DFG_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock)
1801 {
1802     if (Options::verboseOSR())
1803         dataLog(*codeBlock, ": Entered reoptimize\n");
1804     // We must be called with the baseline code block.
1805     ASSERT(JITCode::isBaselineCode(codeBlock->jitType()));
1806
1807     // If I am my own replacement, then reoptimization has already been triggered.
1808     // This can happen in recursive functions.
1809     if (codeBlock->replacement() == codeBlock) {
1810         if (Options::verboseOSR())
1811             dataLog(*codeBlock, ": Not reoptimizing because we've already been jettisoned.\n");
1812         return;
1813     }
1814     
1815     // Otherwise, the replacement must be optimized code. Use this as an opportunity
1816     // to check our logic.
1817     ASSERT(codeBlock->hasOptimizedReplacement());
1818     CodeBlock* optimizedCodeBlock = codeBlock->replacement();
1819     ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
1820
1821     // In order to trigger reoptimization, one of two things must have happened:
1822     // 1) We exited more than some number of times.
1823     // 2) We exited and got stuck in a loop, and now we're exiting again.
1824     bool didExitABunch = optimizedCodeBlock->shouldReoptimizeNow();
1825     bool didGetStuckInLoop =
1826         codeBlock->checkIfOptimizationThresholdReached()
1827         && optimizedCodeBlock->shouldReoptimizeFromLoopNow();
1828     
1829     if (!didExitABunch && !didGetStuckInLoop) {
1830         if (Options::verboseOSR())
1831             dataLog(*codeBlock, ": Not reoptimizing ", *optimizedCodeBlock, " because it either didn't exit enough or didn't loop enough after exit.\n");
1832         codeBlock->optimizeAfterLongWarmUp();
1833         return;
1834     }
1835
1836     codeBlock->reoptimize();
1837 }
1838
1839 } // extern "C"
1840 } } // namespace JSC::DFG
1841
1842 #endif // ENABLE(DFG_JIT)
1843
1844 namespace JSC {
1845
1846 #if COMPILER(GCC) && CPU(X86_64)
1847 asm (
1848 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1849 HIDE_SYMBOL(getHostCallReturnValue) "\n"
1850 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
1851     "mov -40(%r13), %r13\n"
1852     "mov %r13, %rdi\n"
1853     "jmp " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
1854 );
1855 #elif COMPILER(GCC) && CPU(X86)
1856 asm (
1857 ".text" "\n" \
1858 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1859 HIDE_SYMBOL(getHostCallReturnValue) "\n"
1860 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
1861     "mov -40(%edi), %edi\n"
1862     "mov %edi, 4(%esp)\n"
1863     "jmp " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
1864 );
1865 #elif COMPILER(GCC) && CPU(ARM_THUMB2)
1866 asm (
1867 ".text" "\n"
1868 ".align 2" "\n"
1869 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1870 HIDE_SYMBOL(getHostCallReturnValue) "\n"
1871 ".thumb" "\n"
1872 ".thumb_func " THUMB_FUNC_PARAM(getHostCallReturnValue) "\n"
1873 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
1874     "ldr r5, [r5, #-40]" "\n"
1875     "mov r0, r5" "\n"
1876     "b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
1877 );
1878 #elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
1879 asm (
1880 ".text" "\n"
1881 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1882 HIDE_SYMBOL(getHostCallReturnValue) "\n"
1883 INLINE_ARM_FUNCTION(getHostCallReturnValue)
1884 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
1885     "ldr r5, [r5, #-40]" "\n"
1886     "mov r0, r5" "\n"
1887     "b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
1888 );
1889 #elif COMPILER(GCC) && CPU(MIPS)
1890 asm(
1891 ".text" "\n"
1892 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1893 HIDE_SYMBOL(getHostCallReturnValue) "\n"
1894 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
1895     LOAD_FUNCTION_TO_T9(getHostCallReturnValueWithExecState)
1896     "lw $s0, -40($s0)" "\n"
1897     "move $a0, $s0" "\n"
1898     "b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
1899 );
1900 #elif COMPILER(GCC) && CPU(SH4)
1901 asm(
1902 ".text" "\n"
1903 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1904 HIDE_SYMBOL(getHostCallReturnValue) "\n"
1905 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
1906     "add #-40, r14" "\n"
1907     "mov.l @r14, r14" "\n"
1908     "mov r14, r4" "\n"
1909     "mov.l 2f, " SH4_SCRATCH_REGISTER "\n"
1910     "braf " SH4_SCRATCH_REGISTER "\n"
1911     "nop" "\n"
1912     "1: .balign 4" "\n"
1913     "2: .long " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "-1b\n"
1914 );
1915 #endif
1916
1917 extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValueWithExecState(ExecState* exec)
1918 {
1919     if (!exec)
1920         return JSValue::encode(JSValue());
1921     return JSValue::encode(exec->vm().hostCallReturnValue);
1922 }
1923
1924 } // namespace JSC
1925
1926 #endif // ENABLE(JIT)