+2013-10-08 Michael Saboff <msaboff@apple.com>
+
+ Transition call and construct JITStubs to CCallHelper functions
+ https://bugs.webkit.org/show_bug.cgi?id=122453
+
+ Reviewed by Geoffrey Garen.
+
+ Transitioned cti_op_call_eval to operationCallEval. Migrated baseline JIT to use the same
+ call thunks as the DFG. Eliminated all of the "oldStyle" thunks and related functions.
+
+ * bytecode/CallLinkInfo.cpp:
+ (JSC::CallLinkInfo::unlink):
+ * jit/JIT.cpp:
+ (JSC::JIT::linkFor):
+ (JSC::JIT::linkSlowCall):
+ * jit/JIT.h:
+ * jit/JITCall.cpp:
+ (JSC::JIT::compileCallEval):
+ (JSC::JIT::compileCallEvalSlowCase):
+ (JSC::JIT::compileOpCallSlowCase):
+ (JSC::JIT::privateCompileClosureCall):
+ * jit/JITCall32_64.cpp:
+ (JSC::JIT::compileCallEval):
+ (JSC::JIT::compileCallEvalSlowCase):
+ (JSC::JIT::compileOpCallSlowCase):
+ (JSC::JIT::privateCompileClosureCall):
+ * jit/JITInlines.h:
+ (JSC::JIT::callOperationWithCallFrameRollbackOnException):
+ * jit/JITOperations.cpp:
+ * jit/JITOperations.h:
+ * jit/JITStubs.cpp:
+ * jit/JITStubs.h:
+ * jit/ThunkGenerators.cpp:
+ * jit/ThunkGenerators.h:
+
2013-10-09 Julien Brianceau <jbriance@cisco.com>
[sh4] Fix lots of unused parameter warnings.
RELEASE_ASSERT_NOT_REACHED();
#endif
} else
- repatchBuffer.relink(callReturnLocation, callType == Construct ? vm.getCTIStub(oldStyleLinkConstructGenerator).code() : vm.getCTIStub(oldStyleLinkCallGenerator).code());
+ repatchBuffer.relink(callReturnLocation, callType == Construct ? vm.getCTIStub(linkConstructThunkGenerator).code() : vm.getCTIStub(linkCallThunkGenerator).code());
hasSeenShouldRepatch = false;
callee.clear();
stub.clear();
ASSERT(callLinkInfo->callType == CallLinkInfo::Call
|| callLinkInfo->callType == CallLinkInfo::CallVarargs);
if (callLinkInfo->callType == CallLinkInfo::Call) {
- repatchBuffer.relink(callLinkInfo->callReturnLocation, vm->getCTIStub(oldStyleLinkClosureCallGenerator).code());
+ repatchBuffer.relink(callLinkInfo->callReturnLocation, vm->getCTIStub(linkClosureCallThunkGenerator).code());
return;
}
- repatchBuffer.relink(callLinkInfo->callReturnLocation, vm->getCTIStub(oldStyleVirtualCallGenerator).code());
+ repatchBuffer.relink(callLinkInfo->callReturnLocation, vm->getCTIStub(virtualCallThunkGenerator).code());
return;
}
ASSERT(kind == CodeForConstruct);
- repatchBuffer.relink(callLinkInfo->callReturnLocation, vm->getCTIStub(oldStyleVirtualConstructGenerator).code());
+ repatchBuffer.relink(callLinkInfo->callReturnLocation, vm->getCTIStub(virtualConstructThunkGenerator).code());
}
void JIT::linkSlowCall(CodeBlock* callerCodeBlock, CallLinkInfo* callLinkInfo)
{
RepatchBuffer repatchBuffer(callerCodeBlock);
- repatchBuffer.relink(callLinkInfo->callReturnLocation, callerCodeBlock->vm()->getCTIStub(oldStyleVirtualCallGenerator).code());
+ repatchBuffer.relink(callLinkInfo->callReturnLocation, callerCodeBlock->vm()->getCTIStub(virtualCallThunkGenerator).code());
}
void JIT::privateCompileExceptionHandlers()
MacroAssembler::Call appendCallWithExceptionCheckSetJSValueResult(const FunctionPtr&, int);
MacroAssembler::Call callOperation(J_JITOperation_E, int);
MacroAssembler::Call callOperation(J_JITOperation_EP, int, void*);
+ MacroAssembler::Call callOperationWithCallFrameRollbackOnException(J_JITOperation_E);
MacroAssembler::Call callOperationWithCallFrameRollbackOnException(V_JITOperation_ECb, CodeBlock*);
MacroAssembler::Call callOperationWithCallFrameRollbackOnException(Z_JITOperation_E);
void JIT::compileCallEval(Instruction* instruction)
{
- JITStubCall stubCall(this, cti_op_call_eval); // Initializes ScopeChain; ReturnPC; CodeBlock.
- stubCall.call();
+ callOperationWithCallFrameRollbackOnException(operationCallEval);
addSlowCase(branch64(Equal, regT0, TrustedImm64(JSValue::encode(JSValue()))));
emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, callFrameRegister);
linkSlowCase(iter);
emitGetFromCallFrameHeader64(JSStack::Callee, regT0);
- emitNakedCall(m_vm->getCTIStub(oldStyleVirtualCallGenerator).code());
+ emitNakedCall(m_vm->getCTIStub(virtualCallThunkGenerator).code());
sampleCodeBlock(m_codeBlock);
}
linkSlowCase(iter);
-
- m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(opcodeID == op_construct ? m_vm->getCTIStub(oldStyleLinkConstructGenerator).code() : m_vm->getCTIStub(oldStyleLinkCallGenerator).code());
+
+ m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(opcodeID == op_construct ? m_vm->getCTIStub(linkConstructThunkGenerator).code() : m_vm->getCTIStub(linkCallThunkGenerator).code());
sampleCodeBlock(m_codeBlock);
patchBuffer.link(call, FunctionPtr(codePtr.executableAddress()));
patchBuffer.link(done, callLinkInfo->hotPathOther.labelAtOffset(0));
- patchBuffer.link(slow, CodeLocationLabel(m_vm->getCTIStub(oldStyleVirtualCallGenerator).code()));
+ patchBuffer.link(slow, CodeLocationLabel(m_vm->getCTIStub(virtualCallThunkGenerator).code()));
RefPtr<ClosureCallStubRoutine> stubRoutine = adoptRef(new ClosureCallStubRoutine(
FINALIZE_CODE(
repatchBuffer.replaceWithJump(
RepatchBuffer::startOfBranchPtrWithPatchOnRegister(callLinkInfo->hotPathBegin),
CodeLocationLabel(stubRoutine->code().code()));
- repatchBuffer.relink(callLinkInfo->callReturnLocation, m_vm->getCTIStub(oldStyleVirtualCallGenerator).code());
-
+ repatchBuffer.relink(callLinkInfo->callReturnLocation, m_vm->getCTIStub(virtualCallThunkGenerator).code());
+
callLinkInfo->stub = stubRoutine.release();
}
void JIT::compileCallEval(Instruction* instruction)
{
- JITStubCall stubCall(this, cti_op_call_eval); // Initializes ScopeChain; ReturnPC; CodeBlock.
- stubCall.call();
+ callOperationWithCallFrameRollbackOnException(operationCallEval);
addSlowCase(branch32(Equal, regT1, TrustedImm32(JSValue::EmptyValueTag)));
emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, callFrameRegister);
linkSlowCase(iter);
emitLoad(JSStack::Callee, regT1, regT0);
- emitNakedCall(m_vm->getCTIStub(oldStyleVirtualCallGenerator).code());
+ emitNakedCall(m_vm->getCTIStub(virtualCallThunkGenerator).code());
sampleCodeBlock(m_codeBlock);
linkSlowCase(iter);
linkSlowCase(iter);
-
- m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(opcodeID == op_construct ? m_vm->getCTIStub(oldStyleLinkConstructGenerator).code() : m_vm->getCTIStub(oldStyleLinkCallGenerator).code());
+
+ m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(opcodeID == op_construct ? m_vm->getCTIStub(linkConstructThunkGenerator).code() : m_vm->getCTIStub(linkCallThunkGenerator).code());
sampleCodeBlock(m_codeBlock);
emitPutCallResult(instruction);
patchBuffer.link(call, FunctionPtr(codePtr.executableAddress()));
patchBuffer.link(done, callLinkInfo->hotPathOther.labelAtOffset(0));
- patchBuffer.link(slow, CodeLocationLabel(m_vm->getCTIStub(oldStyleVirtualCallGenerator).code()));
+ patchBuffer.link(slow, CodeLocationLabel(m_vm->getCTIStub(virtualCallThunkGenerator).code()));
RefPtr<ClosureCallStubRoutine> stubRoutine = adoptRef(new ClosureCallStubRoutine(
FINALIZE_CODE(
repatchBuffer.replaceWithJump(
RepatchBuffer::startOfBranchPtrWithPatchOnRegister(callLinkInfo->hotPathBegin),
CodeLocationLabel(stubRoutine->code().code()));
- repatchBuffer.relink(callLinkInfo->callReturnLocation, m_vm->getCTIStub(oldStyleVirtualCallGenerator).code());
+ repatchBuffer.relink(callLinkInfo->callReturnLocation, m_vm->getCTIStub(virtualCallThunkGenerator).code());
callLinkInfo->stub = stubRoutine.release();
}
return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
}
+ALWAYS_INLINE MacroAssembler::Call JIT::callOperationWithCallFrameRollbackOnException(J_JITOperation_E operation)
+{
+ setupArgumentsExecState();
+ return appendCallWithCallFrameRollbackOnException(operation);
+}
+
ALWAYS_INLINE MacroAssembler::Call JIT::callOperationWithCallFrameRollbackOnException(V_JITOperation_ECb operation, CodeBlock* pointer)
{
setupArgumentsWithExecState(TrustedImmPtr(pointer));
#include "GetterSetter.h"
#include "HostCallReturnValue.h"
#include "JITOperationWrappers.h"
+#include "JSGlobalObjectFunctions.h"
#include "Operations.h"
#include "Repatch.h"
extern "C" {
+#if COMPILER(MSVC)
+void * _ReturnAddress(void);
+#pragma intrinsic(_ReturnAddress)
+
+#define OUR_RETURN_ADDRESS _ReturnAddress()
+#else
+#define OUR_RETURN_ADDRESS __builtin_return_address(0)
+#endif
+
+#if ENABLE(OPCODE_SAMPLING)
+#define CTI_SAMPLER vm->interpreter->sampler()
+#else
+#define CTI_SAMPLER 0
+#endif
+
+
void JIT_OPERATION operationStackCheck(ExecState* exec, CodeBlock* codeBlock)
{
// We pass in our own code block, because the callframe hasn't been populated.
base->putDirect(vm, offset, JSValue::decode(value));
}
+EncodedJSValue JIT_OPERATION operationCallEval(ExecState* execCallee)
+{
+ CallFrame* callerFrame = execCallee->callerFrame();
+ ASSERT(execCallee->callerFrame()->codeBlock()->codeType() != FunctionCode
+ || !execCallee->callerFrame()->codeBlock()->needsFullScopeChain()
+ || execCallee->callerFrame()->uncheckedR(execCallee->callerFrame()->codeBlock()->activationRegister().offset()).jsValue());
+
+ execCallee->setScope(callerFrame->scope());
+ execCallee->setReturnPC(static_cast<Instruction*>(OUR_RETURN_ADDRESS));
+ execCallee->setCodeBlock(0);
+
+ if (!isHostFunction(execCallee->calleeAsValue(), globalFuncEval))
+ return JSValue::encode(JSValue());
+
+ VM* vm = &execCallee->vm();
+ JSValue result = eval(execCallee);
+ if (vm->exception())
+ return EncodedJSValue();
+
+ return JSValue::encode(result);
+}
+
static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializationKind kind)
{
ExecState* exec = execCallee->callerFrame();
MacroAssemblerCodePtr codePtr;
CodeBlock* codeBlock = 0;
+ CallLinkInfo& callLinkInfo = exec->codeBlock()->getCallLinkInfo(execCallee->returnPC());
if (executable->isHostFunction())
codePtr = executable->generatedJITCodeFor(kind)->addressForCall();
else {
return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
}
codeBlock = functionExecutable->codeBlockFor(kind);
- if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()))
+ if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo.callType == CallLinkInfo::CallVarargs)
codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
else
codePtr = functionExecutable->generatedJITCodeFor(kind)->addressForCall();
}
- CallLinkInfo& callLinkInfo = exec->codeBlock()->getCallLinkInfo(execCallee->returnPC());
if (!callLinkInfo.seenOnce())
callLinkInfo.setSeen();
else
void JIT_OPERATION operationPutByIdDirectStrictBuildList(ExecState*, EncodedJSValue encodedValue, JSCell* base, StringImpl*) WTF_INTERNAL;
void JIT_OPERATION operationPutByIdDirectNonStrictBuildList(ExecState*, EncodedJSValue encodedValue, JSCell* base, StringImpl*) WTF_INTERNAL;
void JIT_OPERATION operationReallocateStorageAndFinishPut(ExecState*, JSObject*, Structure*, PropertyOffset, EncodedJSValue) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationCallEval(ExecState*) WTF_INTERNAL;
char* JIT_OPERATION operationVirtualCall(ExecState*) WTF_INTERNAL;
char* JIT_OPERATION operationLinkCall(ExecState*) WTF_INTERNAL;
char* JIT_OPERATION operationLinkClosureCall(ExecState*) WTF_INTERNAL;
return JSFunction::create(stackFrame.callFrame->vm(), stackFrame.args[0].function(), stackFrame.callFrame->scope());
}
-inline void* jitCompileFor(CallFrame* callFrame, CodeSpecializationKind kind)
-{
- // This function is called by cti_op_call_jitCompile() and
- // cti_op_construct_jitCompile() JIT glue trampolines to compile the
- // callee function that we want to call. Both cti glue trampolines are
- // called by JIT'ed code which has pushed a frame and initialized most of
- // the frame content except for the codeBlock.
- //
- // Normally, the prologue of the callee is supposed to set the frame's cb
- // pointer to the cb of the callee. But in this case, the callee code does
- // not exist yet until it is compiled below. The compilation process will
- // allocate memory which may trigger a GC. The GC, in turn, will scan the
- // JSStack, and will expect the frame's cb to either be valid or 0. If
- // we don't initialize it, the GC will be accessing invalid memory and may
- // crash.
- //
- // Hence, we should nullify it here before proceeding with the compilation.
- callFrame->setCodeBlock(0);
-
- JSFunction* function = jsCast<JSFunction*>(callFrame->callee());
- ASSERT(!function->isHostFunction());
- FunctionExecutable* executable = function->jsExecutable();
- JSScope* callDataScopeChain = function->scope();
- JSObject* error = executable->prepareForExecution(callFrame, callDataScopeChain, kind);
- if (!error)
- return function;
- callFrame->vm().throwException(callFrame, error);
- return 0;
-}
-
-DEFINE_STUB_FUNCTION(void*, op_call_jitCompile)
-{
- STUB_INIT_STACK_FRAME(stackFrame);
-
-#if !ASSERT_DISABLED
- CallData callData;
- ASSERT(stackFrame.callFrame->callee()->methodTable()->getCallData(stackFrame.callFrame->callee(), callData) == CallTypeJS);
-#endif
-
- CallFrame* callFrame = stackFrame.callFrame;
- void* result = jitCompileFor(callFrame, CodeForCall);
- if (!result)
- return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
-
- return result;
-}
-
-DEFINE_STUB_FUNCTION(void*, op_construct_jitCompile)
-{
- STUB_INIT_STACK_FRAME(stackFrame);
-
-#if !ASSERT_DISABLED
- ConstructData constructData;
- ASSERT(jsCast<JSFunction*>(stackFrame.callFrame->callee())->methodTable()->getConstructData(stackFrame.callFrame->callee(), constructData) == ConstructTypeJS);
-#endif
-
- CallFrame* callFrame = stackFrame.callFrame;
- void* result = jitCompileFor(callFrame, CodeForConstruct);
- if (!result)
- return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
-
- return result;
-}
-
-inline void* lazyLinkFor(CallFrame* callFrame, CodeSpecializationKind kind)
-{
- JSFunction* callee = jsCast<JSFunction*>(callFrame->callee());
- ExecutableBase* executable = callee->executable();
-
- MacroAssemblerCodePtr codePtr;
- CodeBlock* codeBlock = 0;
- CallLinkInfo* callLinkInfo = &callFrame->callerFrame()->codeBlock()->getCallLinkInfo(callFrame->returnPC());
-
- // This function is called by cti_vm_lazyLinkCall() and
- // cti_lazyLinkConstruct JIT glue trampolines to link the callee function
- // that we want to call. Both cti glue trampolines are called by JIT'ed
- // code which has pushed a frame and initialized most of the frame content
- // except for the codeBlock.
- //
- // Normally, the prologue of the callee is supposed to set the frame's cb
- // field to the cb of the callee. But in this case, the callee may not
- // exist yet, and if not, it will be generated in the compilation below.
- // The compilation will allocate memory which may trigger a GC. The GC, in
- // turn, will scan the JSStack, and will expect the frame's cb to be valid
- // or 0. If we don't initialize it, the GC will be accessing invalid
- // memory and may crash.
- //
- // Hence, we should nullify it here before proceeding with the compilation.
- callFrame->setCodeBlock(0);
-
- if (executable->isHostFunction())
- codePtr = executable->generatedJITCodeFor(kind)->addressForCall();
- else {
- FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
- if (JSObject* error = functionExecutable->prepareForExecution(callFrame, callee->scope(), kind)) {
- callFrame->vm().throwException(callFrame, error);
- return 0;
- }
- codeBlock = functionExecutable->codeBlockFor(kind);
- if (callFrame->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters())
- || callLinkInfo->callType == CallLinkInfo::CallVarargs)
- codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
- else
- codePtr = functionExecutable->generatedJITCodeFor(kind)->addressForCall();
- }
-
- ConcurrentJITLocker locker(callFrame->callerFrame()->codeBlock()->m_lock);
- if (!callLinkInfo->seenOnce())
- callLinkInfo->setSeen();
- else
- JIT::linkFor(callFrame->callerFrame(), callee, callFrame->callerFrame()->codeBlock(), codeBlock, codePtr, callLinkInfo, &callFrame->vm(), kind);
-
- return codePtr.executableAddress();
-}
-
-DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall)
-{
- STUB_INIT_STACK_FRAME(stackFrame);
-
- CallFrame* callFrame = stackFrame.callFrame;
- void* result = lazyLinkFor(callFrame, CodeForCall);
- if (!result)
- return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
-
- return result;
-}
-
-DEFINE_STUB_FUNCTION(void*, vm_lazyLinkClosureCall)
-{
- STUB_INIT_STACK_FRAME(stackFrame);
-
- CallFrame* callFrame = stackFrame.callFrame;
-
- CodeBlock* callerCodeBlock = callFrame->callerFrame()->codeBlock();
- VM* vm = callerCodeBlock->vm();
- CallLinkInfo* callLinkInfo = &callerCodeBlock->getCallLinkInfo(callFrame->returnPC());
- JSFunction* callee = jsCast<JSFunction*>(callFrame->callee());
- ExecutableBase* executable = callee->executable();
- Structure* structure = callee->structure();
-
- ASSERT(callLinkInfo->callType == CallLinkInfo::Call);
- ASSERT(callLinkInfo->isLinked());
- ASSERT(callLinkInfo->callee);
- ASSERT(callee != callLinkInfo->callee.get());
-
- bool shouldLink = false;
- CodeBlock* calleeCodeBlock = 0;
- MacroAssemblerCodePtr codePtr;
-
- if (executable == callLinkInfo->callee.get()->executable()
- && structure == callLinkInfo->callee.get()->structure()) {
-
- shouldLink = true;
-
- ASSERT(executable->hasJITCodeForCall());
- codePtr = executable->generatedJITCodeForCall()->addressForCall();
- if (!callee->executable()->isHostFunction()) {
- calleeCodeBlock = jsCast<FunctionExecutable*>(executable)->codeBlockForCall();
- if (callFrame->argumentCountIncludingThis() < static_cast<size_t>(calleeCodeBlock->numParameters())) {
- shouldLink = false;
- codePtr = executable->generatedJITCodeWithArityCheckFor(CodeForCall);
- }
- }
- } else if (callee->isHostFunction())
- codePtr = executable->generatedJITCodeForCall()->addressForCall();
- else {
- // Need to clear the code block before compilation, because compilation can GC.
- callFrame->setCodeBlock(0);
-
- FunctionExecutable* functionExecutable = jsCast<FunctionExecutable*>(executable);
- JSScope* scopeChain = callee->scope();
- JSObject* error = functionExecutable->prepareForExecution(callFrame, scopeChain, CodeForCall);
- if (error) {
- callFrame->vm().throwException(callFrame, error);
- return 0;
- }
-
- codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(CodeForCall);
- }
-
- if (shouldLink) {
- ASSERT(codePtr);
- ConcurrentJITLocker locker(callerCodeBlock->m_lock);
- JIT::compileClosureCall(vm, callLinkInfo, callerCodeBlock, calleeCodeBlock, structure, executable, codePtr);
- callLinkInfo->hasSeenClosure = true;
- } else
- JIT::linkSlowCall(callerCodeBlock, callLinkInfo);
-
- return codePtr.executableAddress();
-}
-
-DEFINE_STUB_FUNCTION(void*, vm_lazyLinkConstruct)
-{
- STUB_INIT_STACK_FRAME(stackFrame);
-
- CallFrame* callFrame = stackFrame.callFrame;
- void* result = lazyLinkFor(callFrame, CodeForConstruct);
- if (!result)
- return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
-
- return result;
-}
-
DEFINE_STUB_FUNCTION(JSObject*, op_push_activation)
{
STUB_INIT_STACK_FRAME(stackFrame);
return activation;
}
-DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_NotJSFunction)
-{
- STUB_INIT_STACK_FRAME(stackFrame);
-
- CallFrame* callFrame = stackFrame.callFrame;
-
- JSValue callee = callFrame->calleeAsValue();
-
- CallData callData;
- CallType callType = getCallData(callee, callData);
-
- ASSERT(callType != CallTypeJS);
- if (callType != CallTypeHost) {
- ASSERT(callType == CallTypeNone);
- ErrorWithExecAndCalleeFunctor functor = ErrorWithExecAndCalleeFunctor(createNotAFunctionError, callee);
- return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS, &functor);
- }
-
- EncodedJSValue returnValue;
- {
- SamplingTool::CallRecord callRecord(CTI_SAMPLER, true);
- returnValue = callData.native.function(callFrame);
- }
-
- if (stackFrame.vm->exception())
- return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
-
- return returnValue;
-}
-
DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_arguments)
{
STUB_INIT_STACK_FRAME(stackFrame);
return constructArray(stackFrame.callFrame, stackFrame.args[2].arrayAllocationProfile(), stackFrame.callFrame->codeBlock()->constantBuffer(stackFrame.args[0].int32()), stackFrame.args[1].int32());
}
-DEFINE_STUB_FUNCTION(EncodedJSValue, op_construct_NotJSConstruct)
-{
- STUB_INIT_STACK_FRAME(stackFrame);
-
- CallFrame* callFrame = stackFrame.callFrame;
- JSValue callee = callFrame->calleeAsValue();
-
- ConstructData constructData;
- ConstructType constructType = getConstructData(callee, constructData);
-
- ASSERT(constructType != ConstructTypeJS);
- if (constructType != ConstructTypeHost) {
- ASSERT(constructType == ConstructTypeNone);
- ErrorWithExecAndCalleeFunctor functor = ErrorWithExecAndCalleeFunctor(createNotAConstructorError, callee);
- return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS, &functor);
- }
-
- EncodedJSValue returnValue;
- {
- SamplingTool::CallRecord callRecord(CTI_SAMPLER, true);
- returnValue = constructData.native.function(callFrame);
- }
-
- if (stackFrame.vm->exception())
- return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
-
- return returnValue;
-}
-
static JSValue getByVal(
CallFrame* callFrame, JSValue baseValue, JSValue subscript, ReturnAddressPtr returnAddress)
{
return func;
}
-DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_eval)
-{
- STUB_INIT_STACK_FRAME(stackFrame);
-
- CallFrame* callFrame = stackFrame.callFrame;
- CallFrame* callerFrame = callFrame->callerFrame();
- ASSERT(callFrame->callerFrame()->codeBlock()->codeType() != FunctionCode
- || !callFrame->callerFrame()->codeBlock()->needsFullScopeChain()
- || callFrame->callerFrame()->uncheckedR(callFrame->callerFrame()->codeBlock()->activationRegister().offset()).jsValue());
-
- callFrame->setScope(callerFrame->scope());
- callFrame->setReturnPC(static_cast<Instruction*>((STUB_RETURN_ADDRESS).value()));
- callFrame->setCodeBlock(0);
-
- if (!isHostFunction(callFrame->calleeAsValue(), globalFuncEval))
- return JSValue::encode(JSValue());
-
- JSValue result = eval(callFrame);
- if (stackFrame.vm->exception())
- return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
-
- return JSValue::encode(result);
-}
-
DEFINE_STUB_FUNCTION(void*, op_throw)
{
STUB_INIT_STACK_FRAME(stackFrame);
void performPlatformSpecificJITAssertions(VM*);
extern "C" {
-EncodedJSValue JIT_STUB cti_op_call_NotJSFunction(STUB_ARGS_DECLARATION) WTF_INTERNAL;
-EncodedJSValue JIT_STUB cti_op_call_eval(STUB_ARGS_DECLARATION) WTF_INTERNAL;
-EncodedJSValue JIT_STUB cti_op_construct_NotJSConstruct(STUB_ARGS_DECLARATION) WTF_INTERNAL;
EncodedJSValue JIT_STUB cti_op_check_has_instance(STUB_ARGS_DECLARATION) WTF_INTERNAL;
EncodedJSValue JIT_STUB cti_op_create_arguments(STUB_ARGS_DECLARATION) WTF_INTERNAL;
EncodedJSValue JIT_STUB cti_op_del_by_id(STUB_ARGS_DECLARATION) WTF_INTERNAL;
#if ENABLE(DFG_JIT)
void JIT_STUB cti_optimize(STUB_ARGS_DECLARATION) WTF_INTERNAL;
#endif
-void* JIT_STUB cti_op_call_jitCompile(STUB_ARGS_DECLARATION) WTF_INTERNAL;
-void* JIT_STUB cti_op_construct_jitCompile(STUB_ARGS_DECLARATION) WTF_INTERNAL;
void* JIT_STUB cti_op_switch_char(STUB_ARGS_DECLARATION) WTF_INTERNAL;
void* JIT_STUB cti_op_switch_imm(STUB_ARGS_DECLARATION) WTF_INTERNAL;
void* JIT_STUB cti_op_switch_string(STUB_ARGS_DECLARATION) WTF_INTERNAL;
void* JIT_STUB cti_op_throw(STUB_ARGS_DECLARATION) WTF_INTERNAL;
-void* JIT_STUB cti_vm_lazyLinkCall(STUB_ARGS_DECLARATION) WTF_INTERNAL;
-void* JIT_STUB cti_vm_lazyLinkClosureCall(STUB_ARGS_DECLARATION) WTF_INTERNAL;
-void* JIT_STUB cti_vm_lazyLinkConstruct(STUB_ARGS_DECLARATION) WTF_INTERNAL;
void* JIT_STUB cti_vm_throw(STUB_ARGS_DECLARATION) REFERENCED_FROM_ASM WTF_INTERNAL;
EncodedJSValue JIT_STUB cti_op_resolve_scope(STUB_ARGS_DECLARATION) WTF_INTERNAL;
namespace JSC {
-static JSInterfaceJIT::Call oldStyleGenerateSlowCaseFor(VM* vm, JSInterfaceJIT& jit)
-{
- jit.emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, JSInterfaceJIT::regT2);
- jit.emitGetFromCallFrameHeaderPtr(JSStack::ScopeChain, JSInterfaceJIT::regT2, JSInterfaceJIT::regT2);
- jit.emitPutCellToCallFrameHeader(JSInterfaceJIT::regT2, JSStack::ScopeChain);
-
- // Also initialize ReturnPC and CodeBlock, like a JS function would.
- jit.preserveReturnAddressAfterCall(JSInterfaceJIT::regT3);
- jit.emitPutToCallFrameHeader(JSInterfaceJIT::regT3, JSStack::ReturnPC);
- jit.emitPutImmediateToCallFrameHeader(0, JSStack::CodeBlock);
-
- jit.storePtr(JSInterfaceJIT::callFrameRegister, &vm->topCallFrame);
- jit.restoreArgumentReference();
- JSInterfaceJIT::Call callNotJSFunction = jit.call();
- jit.emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, JSInterfaceJIT::callFrameRegister);
- jit.restoreReturnAddressBeforeReturn(JSInterfaceJIT::regT3);
- jit.ret();
-
- return callNotJSFunction;
-}
-
-static MacroAssemblerCodeRef oldStyleLinkForGenerator(VM* vm, FunctionPtr lazyLink, FunctionPtr notJSFunction, const char* name)
-{
- JSInterfaceJIT jit(vm);
-
- JSInterfaceJIT::JumpList slowCase;
-
-#if USE(JSVALUE64)
- slowCase.append(jit.emitJumpIfNotJSCell(JSInterfaceJIT::regT0));
- slowCase.append(jit.emitJumpIfNotType(JSInterfaceJIT::regT0, JSInterfaceJIT::regT1, JSFunctionType));
-#else // USE(JSVALUE64)
- slowCase.append(jit.branch32(JSInterfaceJIT::NotEqual, JSInterfaceJIT::regT1, JSInterfaceJIT::TrustedImm32(JSValue::CellTag)));
- slowCase.append(jit.emitJumpIfNotType(JSInterfaceJIT::regT0, JSInterfaceJIT::regT1, JSFunctionType));
-#endif // USE(JSVALUE64)
-
- // Finish canonical initialization before JS function call.
- jit.loadPtr(JSInterfaceJIT::Address(JSInterfaceJIT::regT0, JSFunction::offsetOfScopeChain()), JSInterfaceJIT::regT1);
- jit.emitPutCellToCallFrameHeader(JSInterfaceJIT::regT1, JSStack::ScopeChain);
-
- // Also initialize ReturnPC for use by lazy linking and exceptions.
- jit.preserveReturnAddressAfterCall(JSInterfaceJIT::regT3);
- jit.emitPutToCallFrameHeader(JSInterfaceJIT::regT3, JSStack::ReturnPC);
-
- jit.storePtr(JSInterfaceJIT::callFrameRegister, &vm->topCallFrame);
- jit.restoreArgumentReference();
- JSInterfaceJIT::Call callLazyLink = jit.call();
- jit.restoreReturnAddressBeforeReturn(JSInterfaceJIT::regT3);
- jit.jump(JSInterfaceJIT::regT0);
-
- slowCase.link(&jit);
- JSInterfaceJIT::Call callNotJSFunction = oldStyleGenerateSlowCaseFor(vm, jit);
-
- LinkBuffer patchBuffer(*vm, &jit, GLOBAL_THUNK_ID);
- patchBuffer.link(callLazyLink, lazyLink);
- patchBuffer.link(callNotJSFunction, notJSFunction);
-
- return FINALIZE_CODE(patchBuffer, ("link %s trampoline", name));
-}
-
-MacroAssemblerCodeRef oldStyleLinkCallGenerator(VM* vm)
-{
- return oldStyleLinkForGenerator(vm, FunctionPtr(cti_vm_lazyLinkCall), FunctionPtr(cti_op_call_NotJSFunction), "call");
-}
-
-MacroAssemblerCodeRef oldStyleLinkConstructGenerator(VM* vm)
-{
- return oldStyleLinkForGenerator(vm, FunctionPtr(cti_vm_lazyLinkConstruct), FunctionPtr(cti_op_construct_NotJSConstruct), "construct");
-}
-
-MacroAssemblerCodeRef oldStyleLinkClosureCallGenerator(VM* vm)
-{
- return oldStyleLinkForGenerator(vm, FunctionPtr(cti_vm_lazyLinkClosureCall), FunctionPtr(cti_op_call_NotJSFunction), "closure call");
-}
-
-static MacroAssemblerCodeRef oldStyleVirtualForGenerator(VM* vm, FunctionPtr compile, FunctionPtr notJSFunction, const char* name, CodeSpecializationKind kind)
-{
- JSInterfaceJIT jit(vm);
-
- JSInterfaceJIT::JumpList slowCase;
-
-#if USE(JSVALUE64)
- slowCase.append(jit.emitJumpIfNotJSCell(JSInterfaceJIT::regT0));
-#else // USE(JSVALUE64)
- slowCase.append(jit.branch32(JSInterfaceJIT::NotEqual, JSInterfaceJIT::regT1, JSInterfaceJIT::TrustedImm32(JSValue::CellTag)));
-#endif // USE(JSVALUE64)
- slowCase.append(jit.emitJumpIfNotType(JSInterfaceJIT::regT0, JSInterfaceJIT::regT1, JSFunctionType));
-
- // Finish canonical initialization before JS function call.
- jit.loadPtr(JSInterfaceJIT::Address(JSInterfaceJIT::regT0, JSFunction::offsetOfScopeChain()), JSInterfaceJIT::regT1);
- jit.emitPutCellToCallFrameHeader(JSInterfaceJIT::regT1, JSStack::ScopeChain);
-
- jit.loadPtr(JSInterfaceJIT::Address(JSInterfaceJIT::regT0, JSFunction::offsetOfExecutable()), JSInterfaceJIT::regT2);
- JSInterfaceJIT::Jump hasCodeBlock1 = jit.branch32(JSInterfaceJIT::GreaterThanOrEqual, JSInterfaceJIT::Address(JSInterfaceJIT::regT2, FunctionExecutable::offsetOfNumParametersFor(kind)), JSInterfaceJIT::TrustedImm32(0));
- jit.preserveReturnAddressAfterCall(JSInterfaceJIT::regT3);
- jit.storePtr(JSInterfaceJIT::callFrameRegister, &vm->topCallFrame);
- jit.restoreArgumentReference();
- JSInterfaceJIT::Call callCompile = jit.call();
- jit.restoreReturnAddressBeforeReturn(JSInterfaceJIT::regT3);
- jit.loadPtr(JSInterfaceJIT::Address(JSInterfaceJIT::regT0, JSFunction::offsetOfExecutable()), JSInterfaceJIT::regT2);
-
- hasCodeBlock1.link(&jit);
- jit.loadPtr(JSInterfaceJIT::Address(JSInterfaceJIT::regT2, FunctionExecutable::offsetOfJITCodeWithArityCheckFor(kind)), JSInterfaceJIT::regT0);
-#if !ASSERT_DISABLED
- JSInterfaceJIT::Jump ok = jit.branchTestPtr(JSInterfaceJIT::NonZero, JSInterfaceJIT::regT0);
- jit.breakpoint();
- ok.link(&jit);
-#endif
- jit.jump(JSInterfaceJIT::regT0);
-
- slowCase.link(&jit);
- JSInterfaceJIT::Call callNotJSFunction = oldStyleGenerateSlowCaseFor(vm, jit);
-
- LinkBuffer patchBuffer(*vm, &jit, GLOBAL_THUNK_ID);
- patchBuffer.link(callCompile, compile);
- patchBuffer.link(callNotJSFunction, notJSFunction);
-
- return FINALIZE_CODE(patchBuffer, ("virtual %s trampoline", name));
-}
-
-MacroAssemblerCodeRef oldStyleVirtualCallGenerator(VM* vm)
-{
- return oldStyleVirtualForGenerator(vm, FunctionPtr(cti_op_call_jitCompile), FunctionPtr(cti_op_call_NotJSFunction), "call", CodeForCall);
-}
-
-MacroAssemblerCodeRef oldStyleVirtualConstructGenerator(VM* vm)
-{
- return oldStyleVirtualForGenerator(vm, FunctionPtr(cti_op_construct_jitCompile), FunctionPtr(cti_op_construct_NotJSConstruct), "construct", CodeForConstruct);
-}
-
inline void emitPointerValidation(CCallHelpers& jit, GPRReg pointerGPR)
{
#if !ASSERT_DISABLED
#if ENABLE(JIT)
namespace JSC {
-MacroAssemblerCodeRef oldStyleLinkCallGenerator(VM*);
-MacroAssemblerCodeRef oldStyleLinkConstructGenerator(VM*);
-MacroAssemblerCodeRef oldStyleLinkClosureCallGenerator(VM*);
-MacroAssemblerCodeRef oldStyleVirtualCallGenerator(VM*);
-MacroAssemblerCodeRef oldStyleVirtualConstructGenerator(VM*);
-
MacroAssemblerCodeRef throwExceptionFromCallSlowPathGenerator(VM*);
MacroAssemblerCodeRef linkCallThunkGenerator(VM*);