2 * Copyright (C) 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "DFGOperations.h"
31 #include "CodeBlock.h"
32 #include "DFGRepatch.h"
33 #include "Interpreter.h"
34 #include "JSByteArray.h"
35 #include "JSGlobalData.h"
36 #include "Operations.h"
38 #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, register) \
40 ".globl _" STRINGIZE(function) "\n" \
41 "_" STRINGIZE(function) ":" "\n" \
42 "mov (%rsp), %" STRINGIZE(register) "\n" \
43 "jmp _" STRINGIZE(function) "WithReturnAddress" "\n" \
45 #define FUNCTION_WRAPPER_WITH_ARG2_RETURN_ADDRESS(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, rsi)
46 #define FUNCTION_WRAPPER_WITH_ARG4_RETURN_ADDRESS(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, rcx)
47 #define FUNCTION_WRAPPER_WITH_ARG5_RETURN_ADDRESS(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, r8)
49 namespace JSC { namespace DFG {
51 static inline void putByVal(ExecState* exec, JSValue baseValue, uint32_t index, JSValue value)
53 JSGlobalData* globalData = &exec->globalData();
55 if (isJSArray(globalData, baseValue)) {
56 JSArray* array = asArray(baseValue);
57 if (array->canSetIndex(index)) {
58 array->setIndex(*globalData, index, value);
62 array->JSArray::put(exec, index, value);
66 if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(index)) {
67 JSByteArray* byteArray = asByteArray(baseValue);
68 // FIXME: the JITstub used to relink this to an optimized form!
69 if (value.isInt32()) {
70 byteArray->setIndex(index, value.asInt32());
75 if (value.getNumber(dValue)) {
76 byteArray->setIndex(index, dValue);
81 baseValue.put(exec, index, value);
85 ALWAYS_INLINE static void operationPutByValInternal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
87 JSValue baseValue = JSValue::decode(encodedBase);
88 JSValue property = JSValue::decode(encodedProperty);
89 JSValue value = JSValue::decode(encodedValue);
91 if (LIKELY(property.isUInt32())) {
92 putByVal(exec, baseValue, property.asUInt32(), value);
96 if (property.isDouble()) {
97 double propertyAsDouble = property.asDouble();
98 uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
99 if (propertyAsDouble == propertyAsUInt32) {
100 putByVal(exec, baseValue, propertyAsUInt32, value);
105 JSGlobalData* globalData = &exec->globalData();
107 // Don't put to an object if toString throws an exception.
108 Identifier ident(exec, property.toString(exec));
109 if (!globalData->exception) {
110 PutPropertySlot slot(strict);
111 baseValue.put(exec, ident, value, slot);
117 EncodedJSValue operationConvertThis(ExecState* exec, EncodedJSValue encodedOp)
119 return JSValue::encode(JSValue::decode(encodedOp).toThisObject(exec));
122 EncodedJSValue operationValueAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
124 JSValue op1 = JSValue::decode(encodedOp1);
125 JSValue op2 = JSValue::decode(encodedOp2);
127 return JSValue::encode(jsAdd(exec, op1, op2));
130 EncodedJSValue operationValueAddNotNumber(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
132 JSValue op1 = JSValue::decode(encodedOp1);
133 JSValue op2 = JSValue::decode(encodedOp2);
135 ASSERT(!op1.isNumber() || !op2.isNumber());
137 if (op1.isString()) {
139 return JSValue::encode(jsString(exec, asString(op1), asString(op2)));
140 return JSValue::encode(jsString(exec, asString(op1), op2.toPrimitiveString(exec)));
143 return JSValue::encode(jsAddSlowCase(exec, op1, op2));
146 EncodedJSValue operationArithAdd(EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
148 double num1 = JSValue::decode(encodedOp1).uncheckedGetNumber();
149 double num2 = JSValue::decode(encodedOp2).uncheckedGetNumber();
150 return JSValue::encode(jsNumber(num1 + num2));
153 EncodedJSValue operationArithSub(EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
155 double num1 = JSValue::decode(encodedOp1).uncheckedGetNumber();
156 double num2 = JSValue::decode(encodedOp2).uncheckedGetNumber();
157 return JSValue::encode(jsNumber(num1 - num2));
160 EncodedJSValue operationArithMul(EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
162 double num1 = JSValue::decode(encodedOp1).uncheckedGetNumber();
163 double num2 = JSValue::decode(encodedOp2).uncheckedGetNumber();
164 return JSValue::encode(jsNumber(num1 * num2));
167 EncodedJSValue operationArithDiv(EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
169 double num1 = JSValue::decode(encodedOp1).uncheckedGetNumber();
170 double num2 = JSValue::decode(encodedOp2).uncheckedGetNumber();
171 return JSValue::encode(jsNumber(num1 / num2));
174 EncodedJSValue operationArithMod(EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
176 double num1 = JSValue::decode(encodedOp1).uncheckedGetNumber();
177 double num2 = JSValue::decode(encodedOp2).uncheckedGetNumber();
178 return JSValue::encode(jsNumber(fmod(num1, num2)));
181 static inline EncodedJSValue getByVal(ExecState* exec, JSCell* base, uint32_t index)
183 JSGlobalData* globalData = &exec->globalData();
185 // FIXME: the JIT used to handle these in compiled code!
186 if (isJSArray(globalData, base) && asArray(base)->canGetIndex(index))
187 return JSValue::encode(asArray(base)->getIndex(index));
189 // FIXME: the JITstub used to relink this to an optimized form!
190 if (isJSString(globalData, base) && asString(base)->canGetIndex(index))
191 return JSValue::encode(asString(base)->getIndex(exec, index));
193 // FIXME: the JITstub used to relink this to an optimized form!
194 if (isJSByteArray(globalData, base) && asByteArray(base)->canAccessIndex(index))
195 return JSValue::encode(asByteArray(base)->getIndex(exec, index));
197 return JSValue::encode(JSValue(base).get(exec, index));
200 EncodedJSValue operationGetByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty)
202 JSValue baseValue = JSValue::decode(encodedBase);
203 JSValue property = JSValue::decode(encodedProperty);
205 if (LIKELY(baseValue.isCell())) {
206 JSCell* base = baseValue.asCell();
208 if (property.isUInt32()) {
209 return getByVal(exec, base, property.asUInt32());
210 } else if (property.isDouble()) {
211 double propertyAsDouble = property.asDouble();
212 uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
213 if (propertyAsUInt32 == propertyAsDouble)
214 return getByVal(exec, base, propertyAsUInt32);
215 } else if (property.isString()) {
216 if (JSValue result = base->fastGetOwnProperty(exec, asString(property)->value(exec)))
217 return JSValue::encode(result);
221 Identifier ident(exec, property.toString(exec));
222 return JSValue::encode(baseValue.get(exec, ident));
225 EncodedJSValue operationGetById(ExecState* exec, EncodedJSValue encodedBase, Identifier* propertyName)
227 JSValue baseValue = JSValue::decode(encodedBase);
228 PropertySlot slot(baseValue);
229 return JSValue::encode(baseValue.get(exec, *propertyName, slot));
232 EncodedJSValue operationGetMethodOptimizeWithReturnAddress(ExecState*, EncodedJSValue, Identifier*, ReturnAddressPtr);
233 FUNCTION_WRAPPER_WITH_ARG4_RETURN_ADDRESS(operationGetMethodOptimize);
234 EncodedJSValue operationGetMethodOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr returnAddress)
236 JSValue baseValue = JSValue::decode(encodedBase);
237 PropertySlot slot(baseValue);
238 JSValue result = baseValue.get(exec, *propertyName, slot);
240 MethodCallLinkInfo& methodInfo = exec->codeBlock()->getMethodCallLinkInfo(returnAddress);
241 if (methodInfo.seenOnce())
242 dfgRepatchGetMethod(exec, baseValue, *propertyName, slot, methodInfo);
244 methodInfo.setSeen();
246 return JSValue::encode(result);
249 EncodedJSValue operationGetByIdBuildListWithReturnAddress(ExecState*, EncodedJSValue, Identifier*, ReturnAddressPtr);
250 FUNCTION_WRAPPER_WITH_ARG4_RETURN_ADDRESS(operationGetByIdBuildList);
251 EncodedJSValue operationGetByIdBuildListWithReturnAddress(ExecState* exec, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr returnAddress)
253 JSValue baseValue = JSValue::decode(encodedBase);
254 PropertySlot slot(baseValue);
255 JSValue result = baseValue.get(exec, *propertyName, slot);
257 StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
258 dfgBuildGetByIDList(exec, baseValue, *propertyName, slot, stubInfo);
260 return JSValue::encode(result);
263 EncodedJSValue operationGetByIdProtoBuildListWithReturnAddress(ExecState*, EncodedJSValue, Identifier*, ReturnAddressPtr);
264 FUNCTION_WRAPPER_WITH_ARG4_RETURN_ADDRESS(operationGetByIdProtoBuildList);
265 EncodedJSValue operationGetByIdProtoBuildListWithReturnAddress(ExecState* exec, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr returnAddress)
267 JSValue baseValue = JSValue::decode(encodedBase);
268 PropertySlot slot(baseValue);
269 JSValue result = baseValue.get(exec, *propertyName, slot);
271 StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
272 dfgBuildGetByIDProtoList(exec, baseValue, *propertyName, slot, stubInfo);
274 return JSValue::encode(result);
277 EncodedJSValue operationGetByIdOptimizeWithReturnAddress(ExecState*, EncodedJSValue, Identifier*, ReturnAddressPtr);
278 FUNCTION_WRAPPER_WITH_ARG4_RETURN_ADDRESS(operationGetByIdOptimize);
279 EncodedJSValue operationGetByIdOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr returnAddress)
281 JSValue baseValue = JSValue::decode(encodedBase);
282 PropertySlot slot(baseValue);
283 JSValue result = baseValue.get(exec, *propertyName, slot);
285 StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
287 dfgRepatchGetByID(exec, baseValue, *propertyName, slot, stubInfo);
289 stubInfo.seen = true;
291 return JSValue::encode(result);
294 void operationPutByValStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
296 operationPutByValInternal<true>(exec, encodedBase, encodedProperty, encodedValue);
299 void operationPutByValNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
301 operationPutByValInternal<false>(exec, encodedBase, encodedProperty, encodedValue);
304 void operationPutByValBeyondArrayBounds(ExecState* exec, JSArray* array, int32_t index, EncodedJSValue encodedValue)
306 // We should only get here if index is outside the existing vector.
307 ASSERT(!array->canSetIndex(index));
308 array->JSArray::put(exec, index, JSValue::decode(encodedValue));
311 void operationPutByIdStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName)
313 PutPropertySlot slot(true);
314 JSValue::decode(encodedBase).put(exec, *propertyName, JSValue::decode(encodedValue), slot);
317 void operationPutByIdNonStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName)
319 PutPropertySlot slot(false);
320 JSValue::decode(encodedBase).put(exec, *propertyName, JSValue::decode(encodedValue), slot);
323 void operationPutByIdDirectStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName)
325 PutPropertySlot slot(true);
326 JSValue::decode(encodedBase).putDirect(exec, *propertyName, JSValue::decode(encodedValue), slot);
329 void operationPutByIdDirectNonStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName)
331 PutPropertySlot slot(false);
332 JSValue::decode(encodedBase).putDirect(exec, *propertyName, JSValue::decode(encodedValue), slot);
335 void operationPutByIdStrictOptimizeWithReturnAddress(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr);
336 FUNCTION_WRAPPER_WITH_ARG5_RETURN_ADDRESS(operationPutByIdStrictOptimize);
337 void operationPutByIdStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr returnAddress)
339 JSValue value = JSValue::decode(encodedValue);
340 JSValue base = JSValue::decode(encodedBase);
341 PutPropertySlot slot(true);
343 base.put(exec, *propertyName, value, slot);
345 StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
347 dfgRepatchPutByID(exec, base, *propertyName, slot, stubInfo, NotDirect);
349 stubInfo.seen = true;
352 void operationPutByIdNonStrictOptimizeWithReturnAddress(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr);
353 FUNCTION_WRAPPER_WITH_ARG5_RETURN_ADDRESS(operationPutByIdNonStrictOptimize);
354 void operationPutByIdNonStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr returnAddress)
356 JSValue value = JSValue::decode(encodedValue);
357 JSValue base = JSValue::decode(encodedBase);
358 PutPropertySlot slot(false);
360 base.put(exec, *propertyName, value, slot);
362 StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
364 dfgRepatchPutByID(exec, base, *propertyName, slot, stubInfo, NotDirect);
366 stubInfo.seen = true;
369 void operationPutByIdDirectStrictOptimizeWithReturnAddress(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr);
370 FUNCTION_WRAPPER_WITH_ARG5_RETURN_ADDRESS(operationPutByIdDirectStrictOptimize);
371 void operationPutByIdDirectStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr returnAddress)
373 JSValue value = JSValue::decode(encodedValue);
374 JSValue base = JSValue::decode(encodedBase);
375 PutPropertySlot slot(true);
377 base.putDirect(exec, *propertyName, value, slot);
379 StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
381 dfgRepatchPutByID(exec, base, *propertyName, slot, stubInfo, Direct);
383 stubInfo.seen = true;
386 void operationPutByIdDirectNonStrictOptimizeWithReturnAddress(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr);
387 FUNCTION_WRAPPER_WITH_ARG5_RETURN_ADDRESS(operationPutByIdDirectNonStrictOptimize);
388 void operationPutByIdDirectNonStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr returnAddress)
390 JSValue value = JSValue::decode(encodedValue);
391 JSValue base = JSValue::decode(encodedBase);
392 PutPropertySlot slot(false);
394 base.putDirect(exec, *propertyName, value, slot);
396 StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
398 dfgRepatchPutByID(exec, base, *propertyName, slot, stubInfo, Direct);
400 stubInfo.seen = true;
403 RegisterSizedBoolean operationCompareLess(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
405 return jsLess<true>(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
408 RegisterSizedBoolean operationCompareLessEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
410 return jsLessEq<true>(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
413 RegisterSizedBoolean operationCompareGreater(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
415 return jsLess<false>(exec, JSValue::decode(encodedOp2), JSValue::decode(encodedOp1));
418 RegisterSizedBoolean operationCompareGreaterEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
420 return jsLessEq<false>(exec, JSValue::decode(encodedOp2), JSValue::decode(encodedOp1));
423 RegisterSizedBoolean operationCompareEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
425 return JSValue::equalSlowCaseInline(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
428 RegisterSizedBoolean operationCompareStrictEqCell(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
430 JSValue op1 = JSValue::decode(encodedOp1);
431 JSValue op2 = JSValue::decode(encodedOp2);
433 ASSERT(op1.isCell());
434 ASSERT(op2.isCell());
436 return JSValue::strictEqualSlowCaseInline(exec, op1, op2);
439 RegisterSizedBoolean operationCompareStrictEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
441 return JSValue::strictEqual(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
444 EncodedJSValue getHostCallReturnValue();
445 EncodedJSValue getHostCallReturnValueWithExecState(ExecState*);
448 ".globl _" STRINGIZE(getHostCallReturnValue) "\n"
449 "_" STRINGIZE(getHostCallReturnValue) ":" "\n"
450 "mov -40(%r13), %r13\n"
452 "jmp _" STRINGIZE(getHostCallReturnValueWithExecState) "\n"
455 EncodedJSValue getHostCallReturnValueWithExecState(ExecState* exec)
457 return JSValue::encode(exec->globalData().hostCallReturnValue);
460 static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializationKind kind)
462 ExecState* exec = execCallee->callerFrame();
463 JSGlobalData* globalData = &exec->globalData();
464 if (kind == CodeForCall) {
466 CallType callType = getCallData(callee, callData);
468 ASSERT(callType != CallTypeJS);
470 if (callType == CallTypeHost) {
471 if (!globalData->interpreter->registerFile().grow(execCallee->registers())) {
472 globalData->exception = createStackOverflowError(exec);
476 execCallee->setScopeChain(exec->scopeChain());
478 globalData->hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
480 if (globalData->exception)
482 return reinterpret_cast<void*>(getHostCallReturnValue);
485 ASSERT(callType == CallTypeNone);
486 exec->globalData().exception = createNotAFunctionError(exec, callee);
490 ASSERT(kind == CodeForConstruct);
492 ConstructData constructData;
493 ConstructType constructType = getConstructData(callee, constructData);
495 ASSERT(constructType != ConstructTypeJS);
497 if (constructType == ConstructTypeHost) {
498 if (!globalData->interpreter->registerFile().grow(execCallee->registers())) {
499 globalData->exception = createStackOverflowError(exec);
503 execCallee->setScopeChain(exec->scopeChain());
505 globalData->hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee));
507 if (globalData->exception)
509 return reinterpret_cast<void*>(getHostCallReturnValue);
512 ASSERT(constructType == ConstructTypeNone);
513 exec->globalData().exception = createNotAConstructorError(exec, callee);
517 inline void* linkFor(ExecState* execCallee, ReturnAddressPtr returnAddress, CodeSpecializationKind kind)
519 ExecState* exec = execCallee->callerFrame();
520 JSGlobalData* globalData = &exec->globalData();
521 JSValue calleeAsValue = execCallee->calleeAsValue();
522 JSCell* calleeAsFunctionCell = getJSFunction(*globalData, calleeAsValue);
523 if (!calleeAsFunctionCell)
524 return handleHostCall(execCallee, calleeAsValue, kind);
525 JSFunction* callee = asFunction(calleeAsFunctionCell);
526 ExecutableBase* executable = callee->executable();
528 MacroAssemblerCodePtr codePtr;
529 CodeBlock* codeBlock = 0;
530 if (executable->isHostFunction())
531 codePtr = executable->generatedJITCodeFor(kind).addressForCall();
533 execCallee->setScopeChain(callee->scope());
534 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
535 JSObject* error = functionExecutable->compileFor(execCallee, callee->scope(), kind);
537 globalData->exception = createStackOverflowError(exec);
540 codeBlock = &functionExecutable->generatedBytecodeFor(kind);
541 if (execCallee->argumentCountIncludingThis() == static_cast<size_t>(codeBlock->m_numParameters))
542 codePtr = functionExecutable->generatedJITCodeFor(kind).addressForCall();
544 codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
546 CallLinkInfo& callLinkInfo = exec->codeBlock()->getCallLinkInfo(returnAddress);
547 if (!callLinkInfo.seenOnce())
548 callLinkInfo.setSeen();
550 dfgLinkFor(execCallee, callLinkInfo, codeBlock, callee, codePtr, kind);
551 return codePtr.executableAddress();
554 void* operationLinkCallWithReturnAddress(ExecState*, ReturnAddressPtr);
555 FUNCTION_WRAPPER_WITH_ARG2_RETURN_ADDRESS(operationLinkCall);
556 void* operationLinkCallWithReturnAddress(ExecState* execCallee, ReturnAddressPtr returnAddress)
558 return linkFor(execCallee, returnAddress, CodeForCall);
561 void* operationLinkConstructWithReturnAddress(ExecState*, ReturnAddressPtr);
562 FUNCTION_WRAPPER_WITH_ARG2_RETURN_ADDRESS(operationLinkConstruct);
563 void* operationLinkConstructWithReturnAddress(ExecState* execCallee, ReturnAddressPtr returnAddress)
565 return linkFor(execCallee, returnAddress, CodeForConstruct);
568 inline void* virtualFor(ExecState* execCallee, CodeSpecializationKind kind)
570 ExecState* exec = execCallee->callerFrame();
571 JSGlobalData* globalData = &exec->globalData();
572 JSValue calleeAsValue = execCallee->calleeAsValue();
573 JSCell* calleeAsFunctionCell = getJSFunction(*globalData, calleeAsValue);
574 if (UNLIKELY(!calleeAsFunctionCell))
575 return handleHostCall(execCallee, calleeAsValue, kind);
577 JSFunction* function = asFunction(calleeAsFunctionCell);
578 execCallee->setScopeChain(function->scopeUnchecked());
579 ExecutableBase* executable = function->executable();
580 if (UNLIKELY(!executable->hasJITCodeFor(kind))) {
581 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
582 JSObject* error = functionExecutable->compileFor(execCallee, function->scope(), kind);
584 exec->globalData().exception = error;
588 return executable->generatedJITCodeWithArityCheckFor(kind).executableAddress();
591 void* operationVirtualCall(ExecState* execCallee)
593 return virtualFor(execCallee, CodeForCall);
596 void* operationVirtualConstruct(ExecState* execCallee)
598 return virtualFor(execCallee, CodeForConstruct);
601 EncodedJSValue operationInstanceOf(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, EncodedJSValue encodedPrototype)
603 JSValue value = JSValue::decode(encodedValue);
604 JSValue base = JSValue::decode(encodedBase);
605 JSValue prototype = JSValue::decode(encodedPrototype);
607 // Otherwise CheckHasInstance should have failed.
608 ASSERT(base.isCell());
609 // At least one of these checks must have failed to get to the slow case.
610 ASSERT(!value.isCell()
611 || !prototype.isCell()
612 || !prototype.isObject()
613 || (base.asCell()->structure()->typeInfo().flags() & (ImplementsHasInstance | OverridesHasInstance)) != ImplementsHasInstance);
616 // ECMA-262 15.3.5.3:
617 // Throw an exception either if base is not an object, or if it does not implement 'HasInstance' (i.e. is a function).
618 TypeInfo typeInfo(UnspecifiedType);
619 if (!base.isObject() || !(typeInfo = asObject(base)->structure()->typeInfo()).implementsHasInstance()) {
620 throwError(exec, createInvalidParamError(exec, "instanceof", base));
621 return JSValue::encode(jsUndefined());
624 return JSValue::encode(jsBoolean(asObject(base)->hasInstance(exec, value, prototype)));
627 EncodedJSValue operationResolve(ExecState* exec, Identifier* propertyName)
629 ScopeChainNode* scopeChain = exec->scopeChain();
630 ScopeChainIterator iter = scopeChain->begin();
631 ScopeChainIterator end = scopeChain->end();
635 JSObject* record = iter->get();
636 PropertySlot slot(record);
637 if (record->getPropertySlot(exec, *propertyName, slot))
638 return JSValue::encode(slot.getValue(exec, *propertyName));
639 } while (++iter != end);
641 return throwVMError(exec, createUndefinedVariableError(exec, *propertyName));
644 EncodedJSValue operationResolveBase(ExecState* exec, Identifier* propertyName)
646 return JSValue::encode(resolveBase(exec, *propertyName, exec->scopeChain(), false));
649 EncodedJSValue operationResolveBaseStrictPut(ExecState* exec, Identifier* propertyName)
651 JSValue base = resolveBase(exec, *propertyName, exec->scopeChain(), true);
653 throwError(exec, createErrorForInvalidGlobalAssignment(exec, propertyName->ustring()));
654 return JSValue::encode(base);
657 void operationThrowHasInstanceError(ExecState* exec, EncodedJSValue encodedBase)
659 JSValue base = JSValue::decode(encodedBase);
661 // We should only call this function if base is not an object, or if it does not implement 'HasInstance'.
662 ASSERT(!base.isObject() || !asObject(base)->structure()->typeInfo().implementsHasInstance());
664 throwError(exec, createInvalidParamError(exec, "instanceof", base));
667 DFGHandler lookupExceptionHandler(ExecState* exec, ReturnAddressPtr faultLocation)
669 JSValue exceptionValue = exec->exception();
670 ASSERT(exceptionValue);
672 unsigned vPCIndex = exec->codeBlock()->bytecodeOffset(faultLocation);
673 HandlerInfo* handler = exec->globalData().interpreter->throwException(exec, exceptionValue, vPCIndex);
675 void* catchRoutine = handler ? handler->nativeCode.executableAddress() : (void*)ctiOpThrowNotCaught;
676 ASSERT(catchRoutine);
677 return DFGHandler(exec, catchRoutine);
680 double dfgConvertJSValueToNumber(ExecState* exec, EncodedJSValue value)
682 return JSValue::decode(value).toNumber(exec);
685 int32_t dfgConvertJSValueToInt32(ExecState* exec, EncodedJSValue value)
687 return JSValue::decode(value).toInt32(exec);
690 RegisterSizedBoolean dfgConvertJSValueToBoolean(ExecState* exec, EncodedJSValue encodedOp)
692 return JSValue::decode(encodedOp).toBoolean(exec);
695 #if ENABLE(DFG_VERBOSE_SPECULATION_FAILURE)
696 void debugOperationPrintSpeculationFailure(ExecState*, void* debugInfoRaw)
698 SpeculationFailureDebugInfo* debugInfo = static_cast<SpeculationFailureDebugInfo*>(debugInfoRaw);
699 printf("Speculation failure in %p at 0x%x!\n", debugInfo->codeBlock, debugInfo->debugOffset);
704 } } // namespace JSC::DFG