#if USE(JSVALUE64)
#include "JIT.h"
-#include "Arguments.h"
#include "CodeBlock.h"
#include "JITInlines.h"
#include "JSArray.h"
#include "Interpreter.h"
#include "JSCInlines.h"
#include "LinkBuffer.h"
-#include "RepatchBuffer.h"
#include "ResultType.h"
#include "SamplingTool.h"
#include "SetupVarargsFrame.h"
emitPutVirtualRegister(dst);
}
-void JIT::compileSetupVarargsFrame(Instruction* instruction)
+void JIT::compileSetupVarargsFrame(Instruction* instruction, CallLinkInfo* info)
{
int thisValue = instruction[3].u.operand;
int arguments = instruction[4].u.operand;
int firstFreeRegister = instruction[5].u.operand;
int firstVarArgOffset = instruction[6].u.operand;
- JumpList slowCase;
- JumpList end;
- bool canOptimize = m_codeBlock->usesArguments()
- && arguments == m_codeBlock->argumentsRegister().offset()
- && !m_codeBlock->symbolTable()->slowArguments();
-
- if (canOptimize) {
- emitGetVirtualRegister(arguments, regT0);
- slowCase.append(branch64(NotEqual, regT0, TrustedImm64(JSValue::encode(JSValue()))));
-
- move(TrustedImm32(-firstFreeRegister), regT1);
- emitSetupVarargsFrameFastCase(*this, regT1, regT0, regT1, regT2, 0, firstVarArgOffset, slowCase);
- end.append(jump());
- slowCase.link(this);
- }
-
emitGetVirtualRegister(arguments, regT1);
callOperation(operationSizeFrameForVarargs, regT1, -firstFreeRegister, firstVarArgOffset);
move(TrustedImm32(-firstFreeRegister), regT1);
callOperation(operationSetupVarargsFrame, regT1, regT2, firstVarArgOffset, regT0);
move(returnValueGPR, regT1);
- if (canOptimize)
- end.link(this);
+ // Profile the argument count.
+ load32(Address(regT1, JSStack::ArgumentCount * static_cast<int>(sizeof(Register)) + PayloadOffset), regT2);
+ load8(info->addressOfMaxNumArguments(), regT0);
+ Jump notBiggest = branch32(Above, regT0, regT2);
+ Jump notSaturated = branch32(BelowOrEqual, regT2, TrustedImm32(255));
+ move(TrustedImm32(255), regT2);
+ notSaturated.link(this);
+ store8(regT2, info->addressOfMaxNumArguments());
+ notBiggest.link(this);
// Initialize 'this'.
emitGetVirtualRegister(thisValue, regT0);
void JIT::compileCallEvalSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter)
{
+ CallLinkInfo* info = m_codeBlock->addCallLinkInfo();
+ info->setUpCall(CallLinkInfo::Call, CodeOrigin(m_bytecodeOffset), regT0);
+
linkSlowCase(iter);
int registerOffset = -instruction[4].u.operand;
addPtr(TrustedImm32(registerOffset * sizeof(Register) + sizeof(CallerFrameAndPC)), callFrameRegister, stackPointerRegister);
load64(Address(stackPointerRegister, sizeof(Register) * JSStack::Callee - sizeof(CallerFrameAndPC)), regT0);
- move(TrustedImmPtr(&CallLinkInfo::dummy()), regT2);
- emitNakedCall(m_vm->getCTIStub(virtualCallThunkGenerator).code());
+ move(TrustedImmPtr(info), regT2);
+ MacroAssemblerCodeRef virtualThunk = virtualThunkFor(m_vm, *info);
+ info->setSlowStub(createJITStubRoutine(virtualThunk, *m_vm, nullptr, true));
+ emitNakedCall(virtualThunk.code());
addPtr(TrustedImm32(stackPointerOffsetFor(m_codeBlock) * sizeof(Register)), callFrameRegister, stackPointerRegister);
checkStackPointerAlignment();
COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct), call_and_construct_opcodes_must_be_same_length);
COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_call_varargs), call_and_call_varargs_opcodes_must_be_same_length);
COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct_varargs), call_and_construct_varargs_opcodes_must_be_same_length);
+ CallLinkInfo* info;
+ if (opcodeID != op_call_eval)
+ info = m_codeBlock->addCallLinkInfo();
if (opcodeID == op_call_varargs || opcodeID == op_construct_varargs)
- compileSetupVarargsFrame(instruction);
+ compileSetupVarargsFrame(instruction, info);
else {
int argCount = instruction[3].u.operand;
int registerOffset = -instruction[4].u.operand;
} // SP holds newCallFrame + sizeof(CallerFrameAndPC), with ArgumentCount initialized.
uint32_t bytecodeOffset = instruction - m_codeBlock->instructions().begin();
- uint32_t locationBits = CallFrame::Location::encodeAsBytecodeOffset(bytecodeOffset);
+ uint32_t locationBits = CallSiteIndex(bytecodeOffset).bits();
store32(TrustedImm32(locationBits), Address(callFrameRegister, JSStack::ArgumentCount * static_cast<int>(sizeof(Register)) + TagOffset));
emitGetVirtualRegister(callee, regT0); // regT0 holds callee.
store64(regT0, Address(stackPointerRegister, JSStack::Callee * static_cast<int>(sizeof(Register)) - sizeof(CallerFrameAndPC)));
- CallLinkInfo* info = m_codeBlock->addCallLinkInfo();
-
if (opcodeID == op_call_eval) {
compileCallEval(instruction);
return;
addSlowCase(slowCase);
ASSERT(m_callCompilationInfo.size() == callLinkInfoIndex);
- info->callType = CallLinkInfo::callTypeFor(opcodeID);
- info->codeOrigin = CodeOrigin(m_bytecodeOffset);
- info->calleeGPR = regT0;
+ info->setUpCall(CallLinkInfo::callTypeFor(opcodeID), CodeOrigin(m_bytecodeOffset), regT0);
m_callCompilationInfo.append(CallCompilationInfo());
m_callCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck;
m_callCompilationInfo[callLinkInfoIndex].callLinkInfo = info;
linkSlowCase(iter);
- ThunkGenerator generator = linkThunkGeneratorFor(
- (opcodeID == op_construct || opcodeID == op_construct_varargs) ? CodeForConstruct : CodeForCall,
- RegisterPreservationNotRequired);
-
move(TrustedImmPtr(m_callCompilationInfo[callLinkInfoIndex].callLinkInfo), regT2);
- m_callCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_vm->getCTIStub(generator).code());
+ m_callCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_vm->getCTIStub(linkCallThunkGenerator).code());
addPtr(TrustedImm32(stackPointerOffsetFor(m_codeBlock) * sizeof(Register)), callFrameRegister, stackPointerRegister);
checkStackPointerAlignment();