]> git.saurik.com Git - apple/javascriptcore.git/blob - dfg/DFGOperations.cpp
JavaScriptCore-1097.3.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 "CodeBlock.h"
30 #include "DFGOSRExit.h"
31 #include "DFGRepatch.h"
32 #include "HostCallReturnValue.h"
33 #include "GetterSetter.h"
34 #include <wtf/InlineASM.h>
35 #include "Interpreter.h"
36 #include "JITExceptions.h"
37 #include "JSActivation.h"
38 #include "JSGlobalData.h"
39 #include "JSStaticScopeObject.h"
40 #include "Operations.h"
41
42 #if ENABLE(DFG_JIT)
43
44 #if CPU(X86_64)
45
46 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, register) \
47 asm( \
48 ".globl " SYMBOL_STRING(function) "\n" \
49 HIDE_SYMBOL(function) "\n" \
50 SYMBOL_STRING(function) ":" "\n" \
51 "mov (%rsp), %" STRINGIZE(register) "\n" \
52 "jmp " SYMBOL_STRING_RELOCATION(function##WithReturnAddress) "\n" \
53 );
54 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, rsi)
55 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, rcx)
56 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, rcx)
57 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, r8)
58
59 #elif CPU(X86)
60
61 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, offset) \
62 asm( \
63 ".text" "\n" \
64 ".globl " SYMBOL_STRING(function) "\n" \
65 HIDE_SYMBOL(function) "\n" \
66 SYMBOL_STRING(function) ":" "\n" \
67 "mov (%esp), %eax\n" \
68 "mov %eax, " STRINGIZE(offset) "(%esp)\n" \
69 "jmp " SYMBOL_STRING_RELOCATION(function##WithReturnAddress) "\n" \
70 );
71 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, 8)
72 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, 16)
73 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, 20)
74 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, 24)
75
76 #elif COMPILER(GCC) && CPU(ARM_THUMB2)
77
78 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function) \
79 asm ( \
80 ".text" "\n" \
81 ".align 2" "\n" \
82 ".globl " SYMBOL_STRING(function) "\n" \
83 HIDE_SYMBOL(function) "\n" \
84 ".thumb" "\n" \
85 ".thumb_func " THUMB_FUNC_PARAM(function) "\n" \
86 SYMBOL_STRING(function) ":" "\n" \
87 "mov a2, lr" "\n" \
88 "b " SYMBOL_STRING_RELOCATION(function) "WithReturnAddress" "\n" \
89 );
90
91 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function) \
92 asm ( \
93 ".text" "\n" \
94 ".align 2" "\n" \
95 ".globl " SYMBOL_STRING(function) "\n" \
96 HIDE_SYMBOL(function) "\n" \
97 ".thumb" "\n" \
98 ".thumb_func " THUMB_FUNC_PARAM(function) "\n" \
99 SYMBOL_STRING(function) ":" "\n" \
100 "mov a4, lr" "\n" \
101 "b " SYMBOL_STRING_RELOCATION(function) "WithReturnAddress" "\n" \
102 );
103
104 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function) \
105 asm ( \
106 ".text" "\n" \
107 ".align 2" "\n" \
108 ".globl " SYMBOL_STRING(function) "\n" \
109 HIDE_SYMBOL(function) "\n" \
110 ".thumb" "\n" \
111 ".thumb_func " THUMB_FUNC_PARAM(function) "\n" \
112 SYMBOL_STRING(function) ":" "\n" \
113 "str lr, [sp, #0]" "\n" \
114 "b " SYMBOL_STRING_RELOCATION(function) "WithReturnAddress" "\n" \
115 );
116
117 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) \
118 asm ( \
119 ".text" "\n" \
120 ".align 2" "\n" \
121 ".globl " SYMBOL_STRING(function) "\n" \
122 HIDE_SYMBOL(function) "\n" \
123 ".thumb" "\n" \
124 ".thumb_func " THUMB_FUNC_PARAM(function) "\n" \
125 SYMBOL_STRING(function) ":" "\n" \
126 "str lr, [sp, #4]" "\n" \
127 "b " SYMBOL_STRING_RELOCATION(function) "WithReturnAddress" "\n" \
128 );
129
130 #endif
131
132 #define P_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function) \
133 void* DFG_OPERATION function##WithReturnAddress(ExecState*, ReturnAddressPtr); \
134 FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(function)
135
136 #define J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function) \
137 EncodedJSValue DFG_OPERATION function##WithReturnAddress(ExecState*, JSCell*, Identifier*, ReturnAddressPtr); \
138 FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_ECI(function)
139
140 #define J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function) \
141 EncodedJSValue DFG_OPERATION function##WithReturnAddress(ExecState*, EncodedJSValue, Identifier*, ReturnAddressPtr); \
142 FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(function)
143
144 #define V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function) \
145 void DFG_OPERATION function##WithReturnAddress(ExecState*, EncodedJSValue, JSCell*, Identifier*, ReturnAddressPtr); \
146 FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(function)
147
148 namespace JSC { namespace DFG {
149
150 template<bool strict>
151 static inline void putByVal(ExecState* exec, JSValue baseValue, uint32_t index, JSValue value)
152 {
153 JSGlobalData& globalData = exec->globalData();
154 NativeCallFrameTracer tracer(&globalData, exec);
155
156 if (isJSArray(baseValue)) {
157 JSArray* array = asArray(baseValue);
158 if (array->canSetIndex(index)) {
159 array->setIndex(globalData, index, value);
160 return;
161 }
162
163 JSArray::putByIndex(array, exec, index, value, strict);
164 return;
165 }
166
167 baseValue.putByIndex(exec, index, value, strict);
168 }
169
170 template<bool strict>
171 ALWAYS_INLINE static void DFG_OPERATION operationPutByValInternal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
172 {
173 JSGlobalData* globalData = &exec->globalData();
174 NativeCallFrameTracer tracer(globalData, exec);
175
176 JSValue baseValue = JSValue::decode(encodedBase);
177 JSValue property = JSValue::decode(encodedProperty);
178 JSValue value = JSValue::decode(encodedValue);
179
180 if (LIKELY(property.isUInt32())) {
181 putByVal<strict>(exec, baseValue, property.asUInt32(), value);
182 return;
183 }
184
185 if (property.isDouble()) {
186 double propertyAsDouble = property.asDouble();
187 uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
188 if (propertyAsDouble == propertyAsUInt32) {
189 putByVal<strict>(exec, baseValue, propertyAsUInt32, value);
190 return;
191 }
192 }
193
194
195 // Don't put to an object if toString throws an exception.
196 Identifier ident(exec, property.toString(exec)->value(exec));
197 if (!globalData->exception) {
198 PutPropertySlot slot(strict);
199 baseValue.put(exec, ident, value, slot);
200 }
201 }
202
203 extern "C" {
204
205 EncodedJSValue DFG_OPERATION operationConvertThis(ExecState* exec, EncodedJSValue encodedOp)
206 {
207 JSGlobalData* globalData = &exec->globalData();
208 NativeCallFrameTracer tracer(globalData, exec);
209
210 return JSValue::encode(JSValue::decode(encodedOp).toThisObject(exec));
211 }
212
213 inline JSCell* createThis(ExecState* exec, JSCell* prototype, JSFunction* constructor)
214 {
215 #if !ASSERT_DISABLED
216 ConstructData constructData;
217 ASSERT(constructor->methodTable()->getConstructData(constructor, constructData) == ConstructTypeJS);
218 #endif
219
220 JSGlobalData& globalData = exec->globalData();
221 NativeCallFrameTracer tracer(&globalData, exec);
222
223 Structure* structure;
224 if (prototype->isObject())
225 structure = asObject(prototype)->inheritorID(globalData);
226 else
227 structure = constructor->scope()->globalObject->emptyObjectStructure();
228
229 return constructEmptyObject(exec, structure);
230 }
231
232 JSCell* DFG_OPERATION operationCreateThis(ExecState* exec, JSCell* prototype)
233 {
234 JSGlobalData* globalData = &exec->globalData();
235 NativeCallFrameTracer tracer(globalData, exec);
236
237 return createThis(exec, prototype, jsCast<JSFunction*>(exec->callee()));
238 }
239
240 JSCell* DFG_OPERATION operationCreateThisInlined(ExecState* exec, JSCell* prototype, JSCell* constructor)
241 {
242 JSGlobalData* globalData = &exec->globalData();
243 NativeCallFrameTracer tracer(globalData, exec);
244
245 return createThis(exec, prototype, jsCast<JSFunction*>(constructor));
246 }
247
248 JSCell* DFG_OPERATION operationNewObject(ExecState* exec)
249 {
250 JSGlobalData* globalData = &exec->globalData();
251 NativeCallFrameTracer tracer(globalData, exec);
252
253 return constructEmptyObject(exec);
254 }
255
256 EncodedJSValue DFG_OPERATION operationValueAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
257 {
258 JSGlobalData* globalData = &exec->globalData();
259 NativeCallFrameTracer tracer(globalData, exec);
260
261 JSValue op1 = JSValue::decode(encodedOp1);
262 JSValue op2 = JSValue::decode(encodedOp2);
263
264 return JSValue::encode(jsAdd(exec, op1, op2));
265 }
266
267 EncodedJSValue DFG_OPERATION operationValueAddNotNumber(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
268 {
269 JSGlobalData* globalData = &exec->globalData();
270 NativeCallFrameTracer tracer(globalData, exec);
271
272 JSValue op1 = JSValue::decode(encodedOp1);
273 JSValue op2 = JSValue::decode(encodedOp2);
274
275 ASSERT(!op1.isNumber() || !op2.isNumber());
276
277 if (op1.isString() && !op2.isObject())
278 return JSValue::encode(jsString(exec, asString(op1), op2.toString(exec)));
279
280 return JSValue::encode(jsAddSlowCase(exec, op1, op2));
281 }
282
283 static inline EncodedJSValue getByVal(ExecState* exec, JSCell* base, uint32_t index)
284 {
285 JSGlobalData& globalData = exec->globalData();
286 NativeCallFrameTracer tracer(&globalData, exec);
287
288 // FIXME: the JIT used to handle these in compiled code!
289 if (isJSArray(base) && asArray(base)->canGetIndex(index))
290 return JSValue::encode(asArray(base)->getIndex(index));
291
292 // FIXME: the JITstub used to relink this to an optimized form!
293 if (isJSString(base) && asString(base)->canGetIndex(index))
294 return JSValue::encode(asString(base)->getIndex(exec, index));
295
296 return JSValue::encode(JSValue(base).get(exec, index));
297 }
298
299 EncodedJSValue DFG_OPERATION operationGetByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty)
300 {
301 JSGlobalData* globalData = &exec->globalData();
302 NativeCallFrameTracer tracer(globalData, exec);
303
304 JSValue baseValue = JSValue::decode(encodedBase);
305 JSValue property = JSValue::decode(encodedProperty);
306
307 if (LIKELY(baseValue.isCell())) {
308 JSCell* base = baseValue.asCell();
309
310 if (property.isUInt32()) {
311 return getByVal(exec, base, property.asUInt32());
312 } else if (property.isDouble()) {
313 double propertyAsDouble = property.asDouble();
314 uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
315 if (propertyAsUInt32 == propertyAsDouble)
316 return getByVal(exec, base, propertyAsUInt32);
317 } else if (property.isString()) {
318 if (JSValue result = base->fastGetOwnProperty(exec, asString(property)->value(exec)))
319 return JSValue::encode(result);
320 }
321 }
322
323 Identifier ident(exec, property.toString(exec)->value(exec));
324 return JSValue::encode(baseValue.get(exec, ident));
325 }
326
327 EncodedJSValue DFG_OPERATION operationGetByValCell(ExecState* exec, JSCell* base, EncodedJSValue encodedProperty)
328 {
329 JSGlobalData* globalData = &exec->globalData();
330 NativeCallFrameTracer tracer(globalData, exec);
331
332 JSValue property = JSValue::decode(encodedProperty);
333
334 if (property.isUInt32())
335 return getByVal(exec, base, property.asUInt32());
336 if (property.isDouble()) {
337 double propertyAsDouble = property.asDouble();
338 uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
339 if (propertyAsUInt32 == propertyAsDouble)
340 return getByVal(exec, base, propertyAsUInt32);
341 } else if (property.isString()) {
342 if (JSValue result = base->fastGetOwnProperty(exec, asString(property)->value(exec)))
343 return JSValue::encode(result);
344 }
345
346 Identifier ident(exec, property.toString(exec)->value(exec));
347 return JSValue::encode(JSValue(base).get(exec, ident));
348 }
349
350 EncodedJSValue DFG_OPERATION operationGetById(ExecState* exec, EncodedJSValue base, Identifier* propertyName)
351 {
352 JSGlobalData* globalData = &exec->globalData();
353 NativeCallFrameTracer tracer(globalData, exec);
354
355 JSValue baseValue = JSValue::decode(base);
356 PropertySlot slot(baseValue);
357 return JSValue::encode(baseValue.get(exec, *propertyName, slot));
358 }
359
360 J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(operationGetByIdBuildList);
361 EncodedJSValue DFG_OPERATION operationGetByIdBuildListWithReturnAddress(ExecState* exec, EncodedJSValue base, Identifier* propertyName, ReturnAddressPtr returnAddress)
362 {
363 JSGlobalData* globalData = &exec->globalData();
364 NativeCallFrameTracer tracer(globalData, exec);
365
366 JSValue baseValue = JSValue::decode(base);
367 PropertySlot slot(baseValue);
368 JSValue result = baseValue.get(exec, *propertyName, slot);
369
370 StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
371 dfgBuildGetByIDList(exec, baseValue, *propertyName, slot, stubInfo);
372
373 return JSValue::encode(result);
374 }
375
376 J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(operationGetByIdProtoBuildList);
377 EncodedJSValue DFG_OPERATION operationGetByIdProtoBuildListWithReturnAddress(ExecState* exec, EncodedJSValue base, Identifier* propertyName, ReturnAddressPtr returnAddress)
378 {
379 JSGlobalData* globalData = &exec->globalData();
380 NativeCallFrameTracer tracer(globalData, exec);
381
382 JSValue baseValue = JSValue::decode(base);
383 PropertySlot slot(baseValue);
384 JSValue result = baseValue.get(exec, *propertyName, slot);
385
386 StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
387 dfgBuildGetByIDProtoList(exec, baseValue, *propertyName, slot, stubInfo);
388
389 return JSValue::encode(result);
390 }
391
392 J_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJI(operationGetByIdOptimize);
393 EncodedJSValue DFG_OPERATION operationGetByIdOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue base, Identifier* propertyName, ReturnAddressPtr returnAddress)
394 {
395 JSGlobalData* globalData = &exec->globalData();
396 NativeCallFrameTracer tracer(globalData, exec);
397
398 JSValue baseValue = JSValue::decode(base);
399 PropertySlot slot(baseValue);
400 JSValue result = baseValue.get(exec, *propertyName, slot);
401
402 StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
403 if (stubInfo.seen)
404 dfgRepatchGetByID(exec, baseValue, *propertyName, slot, stubInfo);
405 else
406 stubInfo.seen = true;
407
408 return JSValue::encode(result);
409 }
410
411 EncodedJSValue DFG_OPERATION operationCallCustomGetter(ExecState* exec, JSCell* base, PropertySlot::GetValueFunc function, Identifier* ident)
412 {
413 JSGlobalData* globalData = &exec->globalData();
414 NativeCallFrameTracer tracer(globalData, exec);
415
416 return JSValue::encode(function(exec, asObject(base), *ident));
417 }
418
419 EncodedJSValue DFG_OPERATION operationCallGetter(ExecState* exec, JSCell* base, JSCell* value)
420 {
421 JSGlobalData* globalData = &exec->globalData();
422 NativeCallFrameTracer tracer(globalData, exec);
423
424 GetterSetter* getterSetter = asGetterSetter(value);
425 JSObject* getter = getterSetter->getter();
426 if (!getter)
427 return JSValue::encode(jsUndefined());
428 CallData callData;
429 CallType callType = getter->methodTable()->getCallData(getter, callData);
430 return JSValue::encode(call(exec, getter, callType, callData, asObject(base), ArgList()));
431 }
432
433 void DFG_OPERATION operationPutByValStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
434 {
435 JSGlobalData* globalData = &exec->globalData();
436 NativeCallFrameTracer tracer(globalData, exec);
437
438 operationPutByValInternal<true>(exec, encodedBase, encodedProperty, encodedValue);
439 }
440
441 void DFG_OPERATION operationPutByValNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
442 {
443 JSGlobalData* globalData = &exec->globalData();
444 NativeCallFrameTracer tracer(globalData, exec);
445
446 operationPutByValInternal<false>(exec, encodedBase, encodedProperty, encodedValue);
447 }
448
449 void DFG_OPERATION operationPutByValCellStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
450 {
451 JSGlobalData* globalData = &exec->globalData();
452 NativeCallFrameTracer tracer(globalData, exec);
453
454 operationPutByValInternal<true>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
455 }
456
457 void DFG_OPERATION operationPutByValCellNonStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
458 {
459 JSGlobalData* globalData = &exec->globalData();
460 NativeCallFrameTracer tracer(globalData, exec);
461
462 operationPutByValInternal<false>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
463 }
464
465 void DFG_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState* exec, JSArray* array, int32_t index, EncodedJSValue encodedValue)
466 {
467 JSGlobalData* globalData = &exec->globalData();
468 NativeCallFrameTracer tracer(globalData, exec);
469
470 if (index >= 0) {
471 // We should only get here if index is outside the existing vector.
472 ASSERT(!array->canSetIndex(index));
473 JSArray::putByIndex(array, exec, index, JSValue::decode(encodedValue), true);
474 return;
475 }
476
477 PutPropertySlot slot(true);
478 array->methodTable()->put(
479 array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
480 }
481
482 void DFG_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState* exec, JSArray* array, int32_t index, EncodedJSValue encodedValue)
483 {
484 JSGlobalData* globalData = &exec->globalData();
485 NativeCallFrameTracer tracer(globalData, exec);
486
487 if (index >= 0) {
488 // We should only get here if index is outside the existing vector.
489 ASSERT(!array->canSetIndex(index));
490 JSArray::putByIndex(array, exec, index, JSValue::decode(encodedValue), false);
491 return;
492 }
493
494 PutPropertySlot slot(false);
495 array->methodTable()->put(
496 array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
497 }
498
499 EncodedJSValue DFG_OPERATION operationArrayPush(ExecState* exec, EncodedJSValue encodedValue, JSArray* array)
500 {
501 JSGlobalData* globalData = &exec->globalData();
502 NativeCallFrameTracer tracer(globalData, exec);
503
504 array->push(exec, JSValue::decode(encodedValue));
505 return JSValue::encode(jsNumber(array->length()));
506 }
507
508 EncodedJSValue DFG_OPERATION operationRegExpExec(ExecState* exec, JSCell* base, JSCell* argument)
509 {
510 JSGlobalData& globalData = exec->globalData();
511 NativeCallFrameTracer tracer(&globalData, exec);
512
513 if (!base->inherits(&RegExpObject::s_info))
514 return throwVMTypeError(exec);
515
516 ASSERT(argument->isString() || argument->isObject());
517 JSString* input = argument->isString() ? asString(argument) : asObject(argument)->toString(exec);
518 return JSValue::encode(asRegExpObject(base)->exec(exec, input));
519 }
520
521 size_t DFG_OPERATION operationRegExpTest(ExecState* exec, JSCell* base, JSCell* argument)
522 {
523 JSGlobalData& globalData = exec->globalData();
524 NativeCallFrameTracer tracer(&globalData, exec);
525
526 if (!base->inherits(&RegExpObject::s_info)) {
527 throwTypeError(exec);
528 return false;
529 }
530
531 ASSERT(argument->isString() || argument->isObject());
532 JSString* input = argument->isString() ? asString(argument) : asObject(argument)->toString(exec);
533 return asRegExpObject(base)->test(exec, input);
534 }
535
536 EncodedJSValue DFG_OPERATION operationArrayPop(ExecState* exec, JSArray* array)
537 {
538 JSGlobalData* globalData = &exec->globalData();
539 NativeCallFrameTracer tracer(globalData, exec);
540
541 return JSValue::encode(array->pop(exec));
542 }
543
544 void DFG_OPERATION operationPutByIdStrict(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName)
545 {
546 JSGlobalData* globalData = &exec->globalData();
547 NativeCallFrameTracer tracer(globalData, exec);
548
549 PutPropertySlot slot(true);
550 base->methodTable()->put(base, exec, *propertyName, JSValue::decode(encodedValue), slot);
551 }
552
553 void DFG_OPERATION operationPutByIdNonStrict(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName)
554 {
555 JSGlobalData* globalData = &exec->globalData();
556 NativeCallFrameTracer tracer(globalData, exec);
557
558 PutPropertySlot slot(false);
559 base->methodTable()->put(base, exec, *propertyName, JSValue::decode(encodedValue), slot);
560 }
561
562 void DFG_OPERATION operationPutByIdDirectStrict(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName)
563 {
564 JSGlobalData* globalData = &exec->globalData();
565 NativeCallFrameTracer tracer(globalData, exec);
566
567 PutPropertySlot slot(true);
568 ASSERT(base->isObject());
569 asObject(base)->putDirect(exec->globalData(), *propertyName, JSValue::decode(encodedValue), slot);
570 }
571
572 void DFG_OPERATION operationPutByIdDirectNonStrict(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName)
573 {
574 JSGlobalData* globalData = &exec->globalData();
575 NativeCallFrameTracer tracer(globalData, exec);
576
577 PutPropertySlot slot(false);
578 ASSERT(base->isObject());
579 asObject(base)->putDirect(exec->globalData(), *propertyName, JSValue::decode(encodedValue), slot);
580 }
581
582 V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdStrictOptimize);
583 void DFG_OPERATION operationPutByIdStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName, ReturnAddressPtr returnAddress)
584 {
585 JSGlobalData* globalData = &exec->globalData();
586 NativeCallFrameTracer tracer(globalData, exec);
587
588 JSValue value = JSValue::decode(encodedValue);
589 JSValue baseValue(base);
590 PutPropertySlot slot(true);
591
592 baseValue.put(exec, *propertyName, value, slot);
593
594 StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
595 if (stubInfo.seen)
596 dfgRepatchPutByID(exec, baseValue, *propertyName, slot, stubInfo, NotDirect);
597 else
598 stubInfo.seen = true;
599 }
600
601 V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdNonStrictOptimize);
602 void DFG_OPERATION operationPutByIdNonStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName, ReturnAddressPtr returnAddress)
603 {
604 JSGlobalData* globalData = &exec->globalData();
605 NativeCallFrameTracer tracer(globalData, exec);
606
607 JSValue value = JSValue::decode(encodedValue);
608 JSValue baseValue(base);
609 PutPropertySlot slot(false);
610
611 baseValue.put(exec, *propertyName, value, slot);
612
613 StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
614 if (stubInfo.seen)
615 dfgRepatchPutByID(exec, baseValue, *propertyName, slot, stubInfo, NotDirect);
616 else
617 stubInfo.seen = true;
618 }
619
620 V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdDirectStrictOptimize);
621 void DFG_OPERATION operationPutByIdDirectStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName, ReturnAddressPtr returnAddress)
622 {
623 JSGlobalData* globalData = &exec->globalData();
624 NativeCallFrameTracer tracer(globalData, exec);
625
626 JSValue value = JSValue::decode(encodedValue);
627 PutPropertySlot slot(true);
628
629 ASSERT(base->isObject());
630 asObject(base)->putDirect(exec->globalData(), *propertyName, value, slot);
631
632 StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
633 if (stubInfo.seen)
634 dfgRepatchPutByID(exec, base, *propertyName, slot, stubInfo, Direct);
635 else
636 stubInfo.seen = true;
637 }
638
639 V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdDirectNonStrictOptimize);
640 void DFG_OPERATION operationPutByIdDirectNonStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName, ReturnAddressPtr returnAddress)
641 {
642 JSGlobalData* globalData = &exec->globalData();
643 NativeCallFrameTracer tracer(globalData, exec);
644
645 JSValue value = JSValue::decode(encodedValue);
646 PutPropertySlot slot(false);
647
648 ASSERT(base->isObject());
649 asObject(base)->putDirect(exec->globalData(), *propertyName, value, slot);
650
651 StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
652 if (stubInfo.seen)
653 dfgRepatchPutByID(exec, base, *propertyName, slot, stubInfo, Direct);
654 else
655 stubInfo.seen = true;
656 }
657
658 V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdStrictBuildList);
659 void DFG_OPERATION operationPutByIdStrictBuildListWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName, ReturnAddressPtr returnAddress)
660 {
661 JSGlobalData* globalData = &exec->globalData();
662 NativeCallFrameTracer tracer(globalData, exec);
663
664 JSValue value = JSValue::decode(encodedValue);
665 JSValue baseValue(base);
666 PutPropertySlot slot(true);
667
668 baseValue.put(exec, *propertyName, value, slot);
669
670 StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
671 dfgBuildPutByIdList(exec, baseValue, *propertyName, slot, stubInfo, NotDirect);
672 }
673
674 V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdNonStrictBuildList);
675 void DFG_OPERATION operationPutByIdNonStrictBuildListWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName, ReturnAddressPtr returnAddress)
676 {
677 JSGlobalData* globalData = &exec->globalData();
678 NativeCallFrameTracer tracer(globalData, exec);
679
680 JSValue value = JSValue::decode(encodedValue);
681 JSValue baseValue(base);
682 PutPropertySlot slot(false);
683
684 baseValue.put(exec, *propertyName, value, slot);
685
686 StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
687 dfgBuildPutByIdList(exec, baseValue, *propertyName, slot, stubInfo, NotDirect);
688 }
689
690 V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdDirectStrictBuildList);
691 void DFG_OPERATION operationPutByIdDirectStrictBuildListWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName, ReturnAddressPtr returnAddress)
692 {
693 JSGlobalData* globalData = &exec->globalData();
694 NativeCallFrameTracer tracer(globalData, exec);
695
696 JSValue value = JSValue::decode(encodedValue);
697 PutPropertySlot slot(true);
698
699 ASSERT(base->isObject());
700 asObject(base)->putDirect(exec->globalData(), *propertyName, value, slot);
701
702 StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
703 dfgBuildPutByIdList(exec, base, *propertyName, slot, stubInfo, Direct);
704 }
705
706 V_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_EJCI(operationPutByIdDirectNonStrictBuildList);
707 void DFG_OPERATION operationPutByIdDirectNonStrictBuildListWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, JSCell* base, Identifier* propertyName, ReturnAddressPtr returnAddress)
708 {
709 JSGlobalData* globalData = &exec->globalData();
710 NativeCallFrameTracer tracer(globalData, exec);
711
712 JSValue value = JSValue::decode(encodedValue);
713 PutPropertySlot slot(false);
714
715 ASSERT(base->isObject());
716 asObject(base)->putDirect(exec->globalData(), *propertyName, value, slot);
717
718 StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
719 dfgBuildPutByIdList(exec, base, *propertyName, slot, stubInfo, Direct);
720 }
721
722 size_t DFG_OPERATION operationCompareLess(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
723 {
724 JSGlobalData* globalData = &exec->globalData();
725 NativeCallFrameTracer tracer(globalData, exec);
726
727 return jsLess<true>(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
728 }
729
730 size_t DFG_OPERATION operationCompareLessEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
731 {
732 JSGlobalData* globalData = &exec->globalData();
733 NativeCallFrameTracer tracer(globalData, exec);
734
735 return jsLessEq<true>(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
736 }
737
738 size_t DFG_OPERATION operationCompareGreater(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
739 {
740 JSGlobalData* globalData = &exec->globalData();
741 NativeCallFrameTracer tracer(globalData, exec);
742
743 return jsLess<false>(exec, JSValue::decode(encodedOp2), JSValue::decode(encodedOp1));
744 }
745
746 size_t DFG_OPERATION operationCompareGreaterEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
747 {
748 JSGlobalData* globalData = &exec->globalData();
749 NativeCallFrameTracer tracer(globalData, exec);
750
751 return jsLessEq<false>(exec, JSValue::decode(encodedOp2), JSValue::decode(encodedOp1));
752 }
753
754 size_t DFG_OPERATION operationCompareEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
755 {
756 JSGlobalData* globalData = &exec->globalData();
757 NativeCallFrameTracer tracer(globalData, exec);
758
759 return JSValue::equalSlowCaseInline(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
760 }
761
762 size_t DFG_OPERATION operationCompareStrictEqCell(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
763 {
764 JSGlobalData* globalData = &exec->globalData();
765 NativeCallFrameTracer tracer(globalData, exec);
766
767 JSValue op1 = JSValue::decode(encodedOp1);
768 JSValue op2 = JSValue::decode(encodedOp2);
769
770 ASSERT(op1.isCell());
771 ASSERT(op2.isCell());
772
773 return JSValue::strictEqualSlowCaseInline(exec, op1, op2);
774 }
775
776 size_t DFG_OPERATION operationCompareStrictEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
777 {
778 JSGlobalData* globalData = &exec->globalData();
779 NativeCallFrameTracer tracer(globalData, exec);
780
781 JSValue src1 = JSValue::decode(encodedOp1);
782 JSValue src2 = JSValue::decode(encodedOp2);
783
784 return JSValue::strictEqual(exec, src1, src2);
785 }
786
787 static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializationKind kind)
788 {
789 ExecState* exec = execCallee->callerFrame();
790 JSGlobalData* globalData = &exec->globalData();
791
792 execCallee->setScopeChain(exec->scopeChain());
793 execCallee->setCodeBlock(0);
794 execCallee->clearReturnPC();
795
796 if (kind == CodeForCall) {
797 CallData callData;
798 CallType callType = getCallData(callee, callData);
799
800 ASSERT(callType != CallTypeJS);
801
802 if (callType == CallTypeHost) {
803 NativeCallFrameTracer tracer(globalData, execCallee);
804 execCallee->setCallee(asObject(callee));
805 globalData->hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
806 if (globalData->exception)
807 return 0;
808
809 return reinterpret_cast<void*>(getHostCallReturnValue);
810 }
811
812 ASSERT(callType == CallTypeNone);
813 exec->globalData().exception = createNotAFunctionError(exec, callee);
814 return 0;
815 }
816
817 ASSERT(kind == CodeForConstruct);
818
819 ConstructData constructData;
820 ConstructType constructType = getConstructData(callee, constructData);
821
822 ASSERT(constructType != ConstructTypeJS);
823
824 if (constructType == ConstructTypeHost) {
825 NativeCallFrameTracer tracer(globalData, execCallee);
826 execCallee->setCallee(asObject(callee));
827 globalData->hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee));
828 if (globalData->exception)
829 return 0;
830
831 return reinterpret_cast<void*>(getHostCallReturnValue);
832 }
833
834 ASSERT(constructType == ConstructTypeNone);
835 exec->globalData().exception = createNotAConstructorError(exec, callee);
836 return 0;
837 }
838
839 inline void* linkFor(ExecState* execCallee, ReturnAddressPtr returnAddress, CodeSpecializationKind kind)
840 {
841 ExecState* exec = execCallee->callerFrame();
842 JSGlobalData* globalData = &exec->globalData();
843 NativeCallFrameTracer tracer(globalData, exec);
844
845 JSValue calleeAsValue = execCallee->calleeAsValue();
846 JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
847 if (!calleeAsFunctionCell)
848 return handleHostCall(execCallee, calleeAsValue, kind);
849
850 JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell);
851 execCallee->setScopeChain(callee->scopeUnchecked());
852 ExecutableBase* executable = callee->executable();
853
854 MacroAssemblerCodePtr codePtr;
855 CodeBlock* codeBlock = 0;
856 if (executable->isHostFunction())
857 codePtr = executable->generatedJITCodeFor(kind).addressForCall();
858 else {
859 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
860 JSObject* error = functionExecutable->compileFor(execCallee, callee->scope(), kind);
861 if (error) {
862 globalData->exception = createStackOverflowError(exec);
863 return 0;
864 }
865 codeBlock = &functionExecutable->generatedBytecodeFor(kind);
866 if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()))
867 codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
868 else
869 codePtr = functionExecutable->generatedJITCodeFor(kind).addressForCall();
870 }
871 CallLinkInfo& callLinkInfo = exec->codeBlock()->getCallLinkInfo(returnAddress);
872 if (!callLinkInfo.seenOnce())
873 callLinkInfo.setSeen();
874 else
875 dfgLinkFor(execCallee, callLinkInfo, codeBlock, callee, codePtr, kind);
876 return codePtr.executableAddress();
877 }
878
879 P_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(operationLinkCall);
880 void* DFG_OPERATION operationLinkCallWithReturnAddress(ExecState* execCallee, ReturnAddressPtr returnAddress)
881 {
882 return linkFor(execCallee, returnAddress, CodeForCall);
883 }
884
885 P_FUNCTION_WRAPPER_WITH_RETURN_ADDRESS_E(operationLinkConstruct);
886 void* DFG_OPERATION operationLinkConstructWithReturnAddress(ExecState* execCallee, ReturnAddressPtr returnAddress)
887 {
888 return linkFor(execCallee, returnAddress, CodeForConstruct);
889 }
890
891 inline void* virtualFor(ExecState* execCallee, CodeSpecializationKind kind)
892 {
893 ExecState* exec = execCallee->callerFrame();
894 JSGlobalData* globalData = &exec->globalData();
895 NativeCallFrameTracer tracer(globalData, exec);
896
897 JSValue calleeAsValue = execCallee->calleeAsValue();
898 JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
899 if (UNLIKELY(!calleeAsFunctionCell))
900 return handleHostCall(execCallee, calleeAsValue, kind);
901
902 JSFunction* function = jsCast<JSFunction*>(calleeAsFunctionCell);
903 execCallee->setScopeChain(function->scopeUnchecked());
904 ExecutableBase* executable = function->executable();
905 if (UNLIKELY(!executable->hasJITCodeFor(kind))) {
906 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
907 JSObject* error = functionExecutable->compileFor(execCallee, function->scope(), kind);
908 if (error) {
909 exec->globalData().exception = error;
910 return 0;
911 }
912 }
913 return executable->generatedJITCodeWithArityCheckFor(kind).executableAddress();
914 }
915
916 void* DFG_OPERATION operationVirtualCall(ExecState* execCallee)
917 {
918 return virtualFor(execCallee, CodeForCall);
919 }
920
921 void* DFG_OPERATION operationVirtualConstruct(ExecState* execCallee)
922 {
923 return virtualFor(execCallee, CodeForConstruct);
924 }
925
926 EncodedJSValue DFG_OPERATION operationResolve(ExecState* exec, Identifier* propertyName)
927 {
928 JSGlobalData* globalData = &exec->globalData();
929 NativeCallFrameTracer tracer(globalData, exec);
930
931 ScopeChainNode* scopeChain = exec->scopeChain();
932 ScopeChainIterator iter = scopeChain->begin();
933 ScopeChainIterator end = scopeChain->end();
934 ASSERT(iter != end);
935
936 do {
937 JSObject* record = iter->get();
938 PropertySlot slot(record);
939 if (record->getPropertySlot(exec, *propertyName, slot))
940 return JSValue::encode(slot.getValue(exec, *propertyName));
941 } while (++iter != end);
942
943 return throwVMError(exec, createUndefinedVariableError(exec, *propertyName));
944 }
945
946 EncodedJSValue DFG_OPERATION operationResolveBase(ExecState* exec, Identifier* propertyName)
947 {
948 JSGlobalData* globalData = &exec->globalData();
949 NativeCallFrameTracer tracer(globalData, exec);
950
951 return JSValue::encode(resolveBase(exec, *propertyName, exec->scopeChain(), false));
952 }
953
954 EncodedJSValue DFG_OPERATION operationResolveBaseStrictPut(ExecState* exec, Identifier* propertyName)
955 {
956 JSGlobalData* globalData = &exec->globalData();
957 NativeCallFrameTracer tracer(globalData, exec);
958
959 JSValue base = resolveBase(exec, *propertyName, exec->scopeChain(), true);
960 if (!base)
961 throwError(exec, createErrorForInvalidGlobalAssignment(exec, propertyName->ustring()));
962 return JSValue::encode(base);
963 }
964
965 EncodedJSValue DFG_OPERATION operationResolveGlobal(ExecState* exec, GlobalResolveInfo* resolveInfo, Identifier* propertyName)
966 {
967 JSGlobalData* globalData = &exec->globalData();
968 NativeCallFrameTracer tracer(globalData, exec);
969
970 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
971
972 PropertySlot slot(globalObject);
973 if (globalObject->getPropertySlot(exec, *propertyName, slot)) {
974 JSValue result = slot.getValue(exec, *propertyName);
975
976 if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
977 resolveInfo->structure.set(exec->globalData(), exec->codeBlock()->ownerExecutable(), globalObject->structure());
978 resolveInfo->offset = slot.cachedOffset();
979 }
980
981 return JSValue::encode(result);
982 }
983
984 return throwVMError(exec, createUndefinedVariableError(exec, *propertyName));
985 }
986
987 EncodedJSValue DFG_OPERATION operationToPrimitive(ExecState* exec, EncodedJSValue value)
988 {
989 JSGlobalData* globalData = &exec->globalData();
990 NativeCallFrameTracer tracer(globalData, exec);
991
992 return JSValue::encode(JSValue::decode(value).toPrimitive(exec));
993 }
994
995 EncodedJSValue DFG_OPERATION operationStrCat(ExecState* exec, void* buffer, size_t size)
996 {
997 JSGlobalData* globalData = &exec->globalData();
998 NativeCallFrameTracer tracer(globalData, exec);
999
1000 return JSValue::encode(jsString(exec, static_cast<Register*>(buffer), size));
1001 }
1002
1003 EncodedJSValue DFG_OPERATION operationNewArray(ExecState* exec, void* buffer, size_t size)
1004 {
1005 JSGlobalData* globalData = &exec->globalData();
1006 NativeCallFrameTracer tracer(globalData, exec);
1007
1008 return JSValue::encode(constructArray(exec, static_cast<JSValue*>(buffer), size));
1009 }
1010
1011 EncodedJSValue DFG_OPERATION operationNewArrayBuffer(ExecState* exec, size_t start, size_t size)
1012 {
1013 JSGlobalData& globalData = exec->globalData();
1014 NativeCallFrameTracer tracer(&globalData, exec);
1015 return JSValue::encode(constructArray(exec, exec->codeBlock()->constantBuffer(start), size));
1016 }
1017
1018 EncodedJSValue DFG_OPERATION operationNewRegexp(ExecState* exec, void* regexpPtr)
1019 {
1020 JSGlobalData& globalData = exec->globalData();
1021 NativeCallFrameTracer tracer(&globalData, exec);
1022 RegExp* regexp = static_cast<RegExp*>(regexpPtr);
1023 if (!regexp->isValid()) {
1024 throwError(exec, createSyntaxError(exec, "Invalid flags supplied to RegExp constructor."));
1025 return JSValue::encode(jsUndefined());
1026 }
1027
1028 return JSValue::encode(RegExpObject::create(exec->globalData(), exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->regExpStructure(), regexp));
1029 }
1030
1031 JSCell* DFG_OPERATION operationCreateActivation(ExecState* exec)
1032 {
1033 JSGlobalData& globalData = exec->globalData();
1034 NativeCallFrameTracer tracer(&globalData, exec);
1035 JSActivation* activation = JSActivation::create(
1036 globalData, exec, static_cast<FunctionExecutable*>(exec->codeBlock()->ownerExecutable()));
1037 exec->setScopeChain(exec->scopeChain()->push(activation));
1038 return activation;
1039 }
1040
1041 void DFG_OPERATION operationTearOffActivation(ExecState* exec, JSCell* activation)
1042 {
1043 ASSERT(activation);
1044 ASSERT(activation->inherits(&JSActivation::s_info));
1045 JSGlobalData& globalData = exec->globalData();
1046 NativeCallFrameTracer tracer(&globalData, exec);
1047 jsCast<JSActivation*>(activation)->tearOff(exec->globalData());
1048 }
1049
1050 JSCell* DFG_OPERATION operationNewFunction(ExecState* exec, JSCell* functionExecutable)
1051 {
1052 ASSERT(functionExecutable->inherits(&FunctionExecutable::s_info));
1053 JSGlobalData& globalData = exec->globalData();
1054 NativeCallFrameTracer tracer(&globalData, exec);
1055 return static_cast<FunctionExecutable*>(functionExecutable)->make(exec, exec->scopeChain());
1056 }
1057
1058 JSCell* DFG_OPERATION operationNewFunctionExpression(ExecState* exec, JSCell* functionExecutableAsCell)
1059 {
1060 ASSERT(functionExecutableAsCell->inherits(&FunctionExecutable::s_info));
1061 FunctionExecutable* functionExecutable =
1062 static_cast<FunctionExecutable*>(functionExecutableAsCell);
1063 JSFunction *function = functionExecutable->make(exec, exec->scopeChain());
1064 if (!functionExecutable->name().isNull()) {
1065 JSStaticScopeObject* functionScopeObject =
1066 JSStaticScopeObject::create(
1067 exec, functionExecutable->name(), function, ReadOnly | DontDelete);
1068 function->setScope(exec->globalData(), function->scope()->push(functionScopeObject));
1069 }
1070 return function;
1071 }
1072
1073 size_t DFG_OPERATION operationIsObject(EncodedJSValue value)
1074 {
1075 return jsIsObjectType(JSValue::decode(value));
1076 }
1077
1078 size_t DFG_OPERATION operationIsFunction(EncodedJSValue value)
1079 {
1080 return jsIsFunctionType(JSValue::decode(value));
1081 }
1082
1083 double DFG_OPERATION operationFModOnInts(int32_t a, int32_t b)
1084 {
1085 return fmod(a, b);
1086 }
1087
1088 DFGHandlerEncoded DFG_OPERATION lookupExceptionHandler(ExecState* exec, uint32_t callIndex)
1089 {
1090 JSGlobalData* globalData = &exec->globalData();
1091 NativeCallFrameTracer tracer(globalData, exec);
1092
1093 JSValue exceptionValue = exec->exception();
1094 ASSERT(exceptionValue);
1095
1096 unsigned vPCIndex = exec->codeBlock()->bytecodeOffsetForCallAtIndex(callIndex);
1097 ExceptionHandler handler = genericThrow(globalData, exec, exceptionValue, vPCIndex);
1098 ASSERT(handler.catchRoutine);
1099 return dfgHandlerEncoded(handler.callFrame, handler.catchRoutine);
1100 }
1101
1102 DFGHandlerEncoded DFG_OPERATION lookupExceptionHandlerInStub(ExecState* exec, StructureStubInfo* stubInfo)
1103 {
1104 JSGlobalData* globalData = &exec->globalData();
1105 NativeCallFrameTracer tracer(globalData, exec);
1106
1107 JSValue exceptionValue = exec->exception();
1108 ASSERT(exceptionValue);
1109
1110 CodeOrigin codeOrigin = stubInfo->codeOrigin;
1111 while (codeOrigin.inlineCallFrame)
1112 codeOrigin = codeOrigin.inlineCallFrame->caller;
1113
1114 ExceptionHandler handler = genericThrow(globalData, exec, exceptionValue, codeOrigin.bytecodeIndex);
1115 ASSERT(handler.catchRoutine);
1116 return dfgHandlerEncoded(handler.callFrame, handler.catchRoutine);
1117 }
1118
1119 double DFG_OPERATION dfgConvertJSValueToNumber(ExecState* exec, EncodedJSValue value)
1120 {
1121 JSGlobalData* globalData = &exec->globalData();
1122 NativeCallFrameTracer tracer(globalData, exec);
1123
1124 return JSValue::decode(value).toNumber(exec);
1125 }
1126
1127 size_t DFG_OPERATION dfgConvertJSValueToInt32(ExecState* exec, EncodedJSValue value)
1128 {
1129 JSGlobalData* globalData = &exec->globalData();
1130 NativeCallFrameTracer tracer(globalData, exec);
1131
1132 // toInt32/toUInt32 return the same value; we want the value zero extended to fill the register.
1133 return JSValue::decode(value).toUInt32(exec);
1134 }
1135
1136 size_t DFG_OPERATION dfgConvertJSValueToBoolean(ExecState* exec, EncodedJSValue encodedOp)
1137 {
1138 JSGlobalData* globalData = &exec->globalData();
1139 NativeCallFrameTracer tracer(globalData, exec);
1140
1141 return JSValue::decode(encodedOp).toBoolean(exec);
1142 }
1143
1144 #if DFG_ENABLE(VERBOSE_SPECULATION_FAILURE)
1145 void DFG_OPERATION debugOperationPrintSpeculationFailure(ExecState* exec, void* debugInfoRaw)
1146 {
1147 JSGlobalData* globalData = &exec->globalData();
1148 NativeCallFrameTracer tracer(globalData, exec);
1149
1150 SpeculationFailureDebugInfo* debugInfo = static_cast<SpeculationFailureDebugInfo*>(debugInfoRaw);
1151 CodeBlock* codeBlock = debugInfo->codeBlock;
1152 CodeBlock* alternative = codeBlock->alternative();
1153 dataLog("Speculation failure in %p at @%u with executeCounter = %d, "
1154 "reoptimizationRetryCounter = %u, optimizationDelayCounter = %u, "
1155 "success/fail %u/(%u+%u)\n",
1156 codeBlock,
1157 debugInfo->nodeIndex,
1158 alternative ? alternative->jitExecuteCounter() : 0,
1159 alternative ? alternative->reoptimizationRetryCounter() : 0,
1160 alternative ? alternative->optimizationDelayCounter() : 0,
1161 codeBlock->speculativeSuccessCounter(),
1162 codeBlock->speculativeFailCounter(),
1163 codeBlock->forcedOSRExitCounter());
1164 }
1165 #endif
1166
1167 } // extern "C"
1168 } } // namespace JSC::DFG
1169
1170 #endif
1171
1172 #if COMPILER(GCC)
1173
1174 namespace JSC {
1175
1176 #if CPU(X86_64)
1177 asm (
1178 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1179 HIDE_SYMBOL(getHostCallReturnValue) "\n"
1180 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
1181 "mov -40(%r13), %r13\n"
1182 "mov %r13, %rdi\n"
1183 "jmp " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
1184 );
1185 #elif CPU(X86)
1186 asm (
1187 ".text" "\n" \
1188 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1189 HIDE_SYMBOL(getHostCallReturnValue) "\n"
1190 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
1191 "mov -40(%edi), %edi\n"
1192 "mov %edi, 4(%esp)\n"
1193 "jmp " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
1194 );
1195 #elif CPU(ARM_THUMB2)
1196 asm (
1197 ".text" "\n"
1198 ".align 2" "\n"
1199 ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1200 HIDE_SYMBOL(getHostCallReturnValue) "\n"
1201 ".thumb" "\n"
1202 ".thumb_func " THUMB_FUNC_PARAM(getHostCallReturnValue) "\n"
1203 SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
1204 "ldr r5, [r5, #-40]" "\n"
1205 "mov r0, r5" "\n"
1206 "b " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n"
1207 );
1208 #endif
1209
1210 extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValueWithExecState(ExecState* exec)
1211 {
1212 if (!exec)
1213 return JSValue::encode(JSValue());
1214 return JSValue::encode(exec->globalData().hostCallReturnValue);
1215 }
1216
1217 } // namespace JSC
1218
1219 #endif // COMPILER(GCC)
1220