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