]> git.saurik.com Git - apple/javascriptcore.git/blob - dfg/DFGOperations.cpp
JavaScriptCore-1218.33.tar.gz
[apple/javascriptcore.git] / 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 "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) \
313 void* DFG_OPERATION function##WithReturnAddress(ExecState*, ReturnAddressPtr) REFERENCED_FROM_ASM WTF_INTERNAL; \
314 FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function)
315
316 #define J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function) \
317 EncodedJSValue DFG_OPERATION function##WithReturnAddress(ExecState*, JSCell*, Identifier*, ReturnAddressPtr) REFERENCED_FROM_ASM WTF_INTERNAL; \
318 FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function)
319
320 #define J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function) \
321 EncodedJSValue DFG_OPERATION function##WithReturnAddress(ExecState*, EncodedJSValue, Identifier*, ReturnAddressPtr) REFERENCED_FROM_ASM WTF_INTERNAL; \
322 FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function)
323
324 #define V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) \
325 void DFG_OPERATION function##WithReturnAddress(ExecState*, EncodedJSValue, JSCell*, Identifier*, ReturnAddressPtr) REFERENCED_FROM_ASM WTF_INTERNAL; \
326 FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function)
327
328 namespace JSC { namespace DFG {
329
330 template<bool strict>
331 static 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
350 template<bool strict>
351 ALWAYS_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
388 extern "C" {
389
390 EncodedJSValue 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
398 JSCell* 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
411 JSCell* 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
419 EncodedJSValue 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
430 EncodedJSValue 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
446 static 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
463 EncodedJSValue 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
494 EncodedJSValue 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
520 EncodedJSValue 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
534 EncodedJSValue 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
544 J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(operationGetByIdBuildList);
545 EncodedJSValue 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
563 J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(operationGetByIdProtoBuildList);
564 EncodedJSValue 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
582 J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(operationGetByIdOptimize);
583 EncodedJSValue 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
605 EncodedJSValue 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
613 EncodedJSValue 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
627 void 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
635 void 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
643 void 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
651 void 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
659 void 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
674 void 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
689 void 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
706 void 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
723 EncodedJSValue 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
732 EncodedJSValue 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
741 EncodedJSValue 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
749 EncodedJSValue 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
759 EncodedJSValue 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
772 size_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
787 void 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
796 void 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
805 void 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
815 void 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
825 V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdStrictOptimize);
826 void 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
849 V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdNonStrictOptimize);
850 void 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
873 V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdDirectStrictOptimize);
874 void 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
897 V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdDirectNonStrictOptimize);
898 void 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
921 V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdStrictBuildList);
922 void 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
942 V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdNonStrictBuildList);
943 void 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
963 V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdDirectStrictBuildList);
964 void 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
984 V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdDirectNonStrictBuildList);
985 void 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
1005 size_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
1013 size_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
1021 size_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
1029 size_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
1037 size_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)
1046 EncodedJSValue DFG_OPERATION operationCompareStringEq(ExecState* exec, JSCell* left, JSCell* right)
1047 #else
1048 size_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
1062 size_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
1076 size_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
1087 static 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
1138 inline 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
1178 char* DFG_OPERATION operationLinkCall(ExecState* execCallee)
1179 {
1180 return linkFor(execCallee, CodeForCall);
1181 }
1182
1183 char* DFG_OPERATION operationLinkConstruct(ExecState* execCallee)
1184 {
1185 return linkFor(execCallee, CodeForConstruct);
1186 }
1187
1188 inline 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
1213 inline char* virtualFor(ExecState* execCallee, CodeSpecializationKind kind)
1214 {
1215 JSCell* calleeAsFunctionCellIgnored;
1216 return virtualForWithFunction(execCallee, kind, calleeAsFunctionCellIgnored);
1217 }
1218
1219 static 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
1251 char* 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
1263 char* DFG_OPERATION operationVirtualCall(ExecState* execCallee)
1264 {
1265 return virtualFor(execCallee, CodeForCall);
1266 }
1267
1268 char* DFG_OPERATION operationVirtualConstruct(ExecState* execCallee)
1269 {
1270 return virtualFor(execCallee, CodeForConstruct);
1271 }
1272
1273 void DFG_OPERATION operationNotifyGlobalVarWrite(WatchpointSet* watchpointSet)
1274 {
1275 watchpointSet->notifyWrite();
1276 }
1277
1278 EncodedJSValue 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
1285 EncodedJSValue 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
1293 EncodedJSValue 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
1301 EncodedJSValue 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
1312 EncodedJSValue 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
1320 char* 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
1328 char* 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
1336 char* 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
1347 char* 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
1354 EncodedJSValue 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
1367 JSCell* 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
1376 JSCell* 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
1387 JSCell* 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
1399 void 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
1409 void 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
1416 EncodedJSValue 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
1428 EncodedJSValue 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
1443 EncodedJSValue 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
1461 JSCell* 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
1469 EncodedJSValue 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
1477 JSCell* 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
1489 size_t DFG_OPERATION operationIsObject(ExecState* exec, EncodedJSValue value)
1490 {
1491 return jsIsObjectType(exec, JSValue::decode(value));
1492 }
1493
1494 size_t DFG_OPERATION operationIsFunction(EncodedJSValue value)
1495 {
1496 return jsIsFunctionType(JSValue::decode(value));
1497 }
1498
1499 JSCell* DFG_OPERATION operationTypeOf(ExecState* exec, JSCell* value)
1500 {
1501 return jsTypeStringForValue(exec, JSValue(value)).asCell();
1502 }
1503
1504 void 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
1515 char* 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
1524 char* 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
1533 char* 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
1544 char* 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
1554 char* 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
1565 char* 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
1576 char* 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
1587 char* 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
1598 char* 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
1609 StringImpl* 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
1617 JSCell* 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
1625 JSCell* 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
1633 JSCell* 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
1641 JSCell* 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
1649 JSCell* 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
1657 double DFG_OPERATION operationFModOnInts(int32_t a, int32_t b)
1658 {
1659 return fmod(a, b);
1660 }
1661
1662 JSCell* 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
1669 DFGHandlerEncoded 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
1683 DFGHandlerEncoded 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
1700 size_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
1709 size_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
1717 void 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
1755 extern "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
1781 namespace JSC {
1782
1783 #if COMPILER(GCC) && CPU(X86_64)
1784 asm (
1785 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1786 HIDE_SYMBOL(getHostCallReturnValue) "\n"
1787 SYMBOL_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)
1793 asm (
1794 ".text" "\n" \
1795 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1796 HIDE_SYMBOL(getHostCallReturnValue) "\n"
1797 SYMBOL_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)
1803 asm (
1804 ".text" "\n"
1805 ".align 2" "\n"
1806 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1807 HIDE_SYMBOL(getHostCallReturnValue) "\n"
1808 ".thumb" "\n"
1809 ".thumb_func " THUMB_FUNC_PARAM(getHostCallReturnValue) "\n"
1810 SYMBOL_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)
1816 asm (
1817 ".text" "\n"
1818 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1819 HIDE_SYMBOL(getHostCallReturnValue) "\n"
1820 INLINE_ARM_FUNCTION(getHostCallReturnValue)
1821 SYMBOL_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)
1827 asm (
1828 ".text" "\n"
1829 ".align 2" "\n"
1830 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1831 HIDE_SYMBOL(getHostCallReturnValue) "\n"
1832 SYMBOL_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)
1838 asm(
1839 ".text" "\n"
1840 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1841 HIDE_SYMBOL(getHostCallReturnValue) "\n"
1842 SYMBOL_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)
1849 asm(
1850 ".text" "\n"
1851 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1852 HIDE_SYMBOL(getHostCallReturnValue) "\n"
1853 SYMBOL_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
1862 extern "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)