JITPropertyAccess.cpp [plain text]
#include "config.h"
#include "JIT.h"
#if ENABLE(JIT)
#include "CodeBlock.h"
#include "JITInlineMethods.h"
#include "JSArray.h"
#include "JSFunction.h"
#include "Interpreter.h"
#include "ResultType.h"
#include "SamplingTool.h"
#ifndef NDEBUG
#include <stdio.h>
#endif
using namespace std;
namespace JSC {
#if !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
void JIT::compileGetByIdHotPath(int resultVReg, int baseVReg, Identifier* ident, unsigned)
{
emitGetVirtualRegister(baseVReg, X86::eax);
emitPutJITStubArg(X86::eax, 1);
emitPutJITStubArgConstant(ident, 2);
emitCTICall(Interpreter::cti_op_get_by_id_generic);
emitPutVirtualRegister(resultVReg);
}
void JIT::compileGetByIdSlowCase(int, int, Identifier*, Vector<SlowCaseEntry>::iterator&, unsigned)
{
ASSERT_NOT_REACHED();
}
void JIT::compilePutByIdHotPath(int baseVReg, Identifier* ident, int valueVReg, unsigned)
{
emitGetVirtualRegisters(baseVReg, X86::eax, valueVReg, X86::edx);
emitPutJITStubArgConstant(ident, 2);
emitPutJITStubArg(X86::eax, 1);
emitPutJITStubArg(X86::edx, 3);
emitCTICall(Interpreter::cti_op_put_by_id_generic);
}
void JIT::compilePutByIdSlowCase(int, Identifier*, int, Vector<SlowCaseEntry>::iterator&, unsigned)
{
ASSERT_NOT_REACHED();
}
#else
void JIT::compileGetByIdHotPath(int resultVReg, int baseVReg, Identifier*, unsigned propertyAccessInstructionIndex)
{
emitGetVirtualRegister(baseVReg, X86::eax);
emitJumpSlowCaseIfNotJSCell(X86::eax, baseVReg);
Label hotPathBegin(this);
m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;
DataLabelPtr structureToCompare;
Jump structureCheck = jnePtrWithPatch(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
addSlowCase(structureCheck);
ASSERT(differenceBetween(hotPathBegin, structureToCompare) == patchOffsetGetByIdStructure);
ASSERT(differenceBetween(hotPathBegin, structureCheck) == patchOffsetGetByIdBranchToSlowCase);
loadPtr(Address(X86::eax, FIELD_OFFSET(JSObject, m_propertyStorage)), X86::eax);
DataLabel32 displacementLabel = loadPtrWithAddressOffsetPatch(Address(X86::eax, patchGetByIdDefaultOffset), X86::eax);
ASSERT(differenceBetween(hotPathBegin, displacementLabel) == patchOffsetGetByIdPropertyMapOffset);
Label putResult(this);
ASSERT(differenceBetween(hotPathBegin, putResult) == patchOffsetGetByIdPutResult);
emitPutVirtualRegister(resultVReg);
}
void JIT::compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, unsigned propertyAccessInstructionIndex)
{
linkSlowCaseIfNotJSCell(iter, baseVReg);
linkSlowCase(iter);
#ifndef NDEBUG
Label coldPathBegin(this);
#endif
emitPutJITStubArg(X86::eax, 1);
emitPutJITStubArgConstant(ident, 2);
Jump call = emitCTICall(Interpreter::cti_op_get_by_id);
emitPutVirtualRegister(resultVReg);
ASSERT(differenceBetween(coldPathBegin, call) == patchOffsetGetByIdSlowCaseCall);
m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].callReturnLocation = call;
}
void JIT::compilePutByIdHotPath(int baseVReg, Identifier*, int valueVReg, unsigned propertyAccessInstructionIndex)
{
emitGetVirtualRegisters(baseVReg, X86::eax, valueVReg, X86::edx);
emitJumpSlowCaseIfNotJSCell(X86::eax, baseVReg);
Label hotPathBegin(this);
m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;
DataLabelPtr structureToCompare;
addSlowCase(jnePtrWithPatch(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))));
ASSERT(differenceBetween(hotPathBegin, structureToCompare) == patchOffsetPutByIdStructure);
loadPtr(Address(X86::eax, FIELD_OFFSET(JSObject, m_propertyStorage)), X86::eax);
DataLabel32 displacementLabel = storePtrWithAddressOffsetPatch(X86::edx, Address(X86::eax, patchGetByIdDefaultOffset));
ASSERT(differenceBetween(hotPathBegin, displacementLabel) == patchOffsetPutByIdPropertyMapOffset);
}
void JIT::compilePutByIdSlowCase(int baseVReg, Identifier* ident, int, Vector<SlowCaseEntry>::iterator& iter, unsigned propertyAccessInstructionIndex)
{
linkSlowCaseIfNotJSCell(iter, baseVReg);
linkSlowCase(iter);
emitPutJITStubArgConstant(ident, 2);
emitPutJITStubArg(X86::eax, 1);
emitPutJITStubArg(X86::edx, 3);
Jump call = emitCTICall(Interpreter::cti_op_put_by_id);
m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].callReturnLocation = call;
}
static JSObject* resizePropertyStorage(JSObject* baseObject, int32_t oldSize, int32_t newSize)
{
baseObject->allocatePropertyStorage(oldSize, newSize);
return baseObject;
}
static inline bool transitionWillNeedStorageRealloc(Structure* oldStructure, Structure* newStructure)
{
return oldStructure->propertyStorageCapacity() != newStructure->propertyStorageCapacity();
}
void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, void* returnAddress)
{
JumpList failureCases;
failureCases.append(emitJumpIfNotJSCell(X86::eax));
failureCases.append(jnePtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), ImmPtr(oldStructure)));
JumpList successCases;
loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::ecx);
failureCases.append(jne32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo) + FIELD_OFFSET(TypeInfo, m_type)), Imm32(ObjectType)));
loadPtr(Address(X86::ecx, FIELD_OFFSET(Structure, m_prototype)), X86::ecx);
for (RefPtr<Structure>* it = chain->head(); *it; ++it) {
successCases.append(jePtr(X86::ecx, ImmPtr(JSValuePtr::encode(jsNull()))));
failureCases.append(jnePtr(Address(X86::ecx, FIELD_OFFSET(JSCell, m_structure)), ImmPtr(it->get())));
loadPtr(Address(X86::ecx, FIELD_OFFSET(JSCell, m_structure)), X86::ecx);
failureCases.append(jne32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo) + FIELD_OFFSET(TypeInfo, m_type)), Imm32(ObjectType)));
loadPtr(Address(X86::ecx, FIELD_OFFSET(Structure, m_prototype)), X86::ecx);
}
successCases.link(this);
Jump callTarget;
if (transitionWillNeedStorageRealloc(oldStructure, newStructure)) {
pop(X86::ebx);
#if PLATFORM(X86_64)
move(Imm32(newStructure->propertyStorageCapacity()), X86::edx);
move(Imm32(oldStructure->propertyStorageCapacity()), X86::esi);
move(X86::eax, X86::edi);
callTarget = call();
#else
push(Imm32(newStructure->propertyStorageCapacity()));
push(Imm32(oldStructure->propertyStorageCapacity()));
push(X86::eax);
callTarget = call();
addPtr(Imm32(3 * sizeof(void*)), X86::esp);
#endif
emitGetJITStubArg(3, X86::edx);
push(X86::ebx);
}
sub32(Imm32(1), AbsoluteAddress(oldStructure->addressOfCount()));
add32(Imm32(1), AbsoluteAddress(newStructure->addressOfCount()));
storePtr(ImmPtr(newStructure), Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)));
loadPtr(Address(X86::eax, FIELD_OFFSET(JSObject, m_propertyStorage)), X86::eax);
storePtr(X86::edx, Address(X86::eax, cachedOffset * sizeof(JSValuePtr)));
ret();
Jump failureJump;
bool plantedFailureJump = false;
if (!failureCases.empty()) {
failureCases.link(this);
restoreArgumentReferenceForTrampoline();
failureJump = jump();
plantedFailureJump = true;
}
void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
PatchBuffer patchBuffer(code);
if (plantedFailureJump)
patchBuffer.link(failureJump, reinterpret_cast<void*>(Interpreter::cti_op_put_by_id_fail));
if (transitionWillNeedStorageRealloc(oldStructure, newStructure))
patchBuffer.link(callTarget, reinterpret_cast<void*>(resizePropertyStorage));
stubInfo->stubRoutine = code;
Jump::patch(returnAddress, code);
}
void JIT::patchGetByIdSelf(StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, void* returnAddress)
{
Jump::patch(returnAddress, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_self_fail));
void* structureAddress = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + patchOffsetGetByIdStructure);
void* displacementAddress = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + patchOffsetGetByIdPropertyMapOffset);
DataLabelPtr::patch(structureAddress, structure);
DataLabel32::patch(displacementAddress, cachedOffset * sizeof(JSValuePtr));
}
void JIT::patchPutByIdReplace(StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, void* returnAddress)
{
Jump::patch(returnAddress, reinterpret_cast<void*>(Interpreter::cti_op_put_by_id_generic));
void* structureAddress = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetPutByIdStructure;
void* displacementAddress = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetPutByIdPropertyMapOffset;
DataLabelPtr::patch(structureAddress, structure);
DataLabel32::patch(displacementAddress, cachedOffset * sizeof(JSValuePtr));
}
void JIT::privateCompilePatchGetArrayLength(void* returnAddress)
{
StructureStubInfo* stubInfo = &m_codeBlock->getStubInfo(returnAddress);
Jump::patch(returnAddress, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_array_fail));
Jump failureCases1 = jnePtr(Address(X86::eax), ImmPtr(m_interpreter->m_jsArrayVptr));
loadPtr(Address(X86::eax, FIELD_OFFSET(JSArray, m_storage)), X86::ecx);
load32(Address(X86::ecx, FIELD_OFFSET(ArrayStorage, m_length)), X86::ecx);
Jump failureCases2 = ja32(X86::ecx, Imm32(JSImmediate::maxImmediateInt));
emitFastArithIntToImmNoCheck(X86::ecx, X86::eax);
Jump success = jump();
void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
PatchBuffer patchBuffer(code);
void* slowCaseBegin = reinterpret_cast<char*>(stubInfo->callReturnLocation) - patchOffsetGetByIdSlowCaseCall;
patchBuffer.link(failureCases1, slowCaseBegin);
patchBuffer.link(failureCases2, slowCaseBegin);
void* hotPathPutResult = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetGetByIdPutResult;
patchBuffer.link(success, hotPathPutResult);
stubInfo->stubRoutine = code;
void* jumpLocation = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetGetByIdBranchToSlowCase;
Jump::patch(jumpLocation, code);
}
void JIT::privateCompileGetByIdSelf(StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, void* returnAddress)
{
Jump failureCases1 = emitJumpIfNotJSCell(X86::eax);
Jump failureCases2 = checkStructure(X86::eax, structure);
loadPtr(Address(X86::eax, FIELD_OFFSET(JSObject, m_propertyStorage)), X86::eax);
loadPtr(Address(X86::eax, cachedOffset * sizeof(JSValuePtr)), X86::eax);
ret();
void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
PatchBuffer patchBuffer(code);
patchBuffer.link(failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_self_fail));
patchBuffer.link(failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_self_fail));
stubInfo->stubRoutine = code;
Jump::patch(returnAddress, code);
}
void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, void* returnAddress, CallFrame* callFrame)
{
#if USE(CTI_REPATCH_PIC)
Jump::patch(returnAddress, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_list));
JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
loadPtr(static_cast<void*>(protoPropertyStorage), X86::edx);
Jump failureCases1 = checkStructure(X86::eax, structure);
Structure** prototypeStructureAddress = &(protoObject->m_structure);
#if PLATFORM(X86_64)
move(ImmPtr(prototypeStructure), X86::ebx);
Jump failureCases2 = jnePtr(X86::ebx, AbsoluteAddress(prototypeStructureAddress));
#else
Jump failureCases2 = jnePtr(AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure));
#endif
loadPtr(Address(X86::edx, cachedOffset * sizeof(JSValuePtr)), X86::eax);
Jump success = jump();
void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
PatchBuffer patchBuffer(code);
void* slowCaseBegin = reinterpret_cast<char*>(stubInfo->callReturnLocation) - patchOffsetGetByIdSlowCaseCall;
patchBuffer.link(failureCases1, slowCaseBegin);
patchBuffer.link(failureCases2, slowCaseBegin);
intptr_t successDest = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + patchOffsetGetByIdPutResult;
patchBuffer.link(success, reinterpret_cast<void*>(successDest));
stubInfo->stubRoutine = code;
void* jumpLocation = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetGetByIdBranchToSlowCase;
Jump::patch(jumpLocation, code);
#else
JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
loadPtr(protoPropertyStorage, X86::edx);
Jump failureCases1 = emitJumpIfNotJSCell(X86::eax);
Jump failureCases2 = checkStructure(X86::eax, structure);
Structure** prototypeStructureAddress = &(protoObject->m_structure);
Jump failureCases3 = jnePtr(AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure));
loadPtr(Address(X86::edx, cachedOffset * sizeof(JSValuePtr)), X86::eax);
ret();
void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
PatchBuffer patchBuffer(code);
patchBuffer.link(failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_fail));
patchBuffer.link(failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_fail));
patchBuffer.link(failureCases3, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_fail));
stubInfo->stubRoutine = code;
Jump::patch(returnAddress, code);
#endif
}
#if USE(CTI_REPATCH_PIC)
void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, size_t cachedOffset)
{
Jump failureCase = checkStructure(X86::eax, structure);
loadPtr(Address(X86::eax, FIELD_OFFSET(JSObject, m_propertyStorage)), X86::eax);
loadPtr(Address(X86::eax, cachedOffset * sizeof(JSValuePtr)), X86::eax);
Jump success = jump();
void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
ASSERT(code);
PatchBuffer patchBuffer(code);
void* lastProtoBegin = polymorphicStructures->list[currentIndex - 1].stubRoutine;
if (!lastProtoBegin)
lastProtoBegin = reinterpret_cast<char*>(stubInfo->callReturnLocation) - patchOffsetGetByIdSlowCaseCall;
patchBuffer.link(failureCase, lastProtoBegin);
intptr_t successDest = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + patchOffsetGetByIdPutResult;
patchBuffer.link(success, reinterpret_cast<void*>(successDest));
structure->ref();
polymorphicStructures->list[currentIndex].set(code, structure);
void* jumpLocation = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetGetByIdBranchToSlowCase;
Jump::patch(jumpLocation, code);
}
void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, CallFrame* callFrame)
{
JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
loadPtr(protoPropertyStorage, X86::edx);
Jump failureCases1 = checkStructure(X86::eax, structure);
Structure** prototypeStructureAddress = &(protoObject->m_structure);
#if PLATFORM(X86_64)
move(ImmPtr(prototypeStructure), X86::ebx);
Jump failureCases2 = jnePtr(X86::ebx, AbsoluteAddress(prototypeStructureAddress));
#else
Jump failureCases2 = jnePtr(AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure));
#endif
loadPtr(Address(X86::edx, cachedOffset * sizeof(JSValuePtr)), X86::eax);
Jump success = jump();
void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
PatchBuffer patchBuffer(code);
void* lastProtoBegin = prototypeStructures->list[currentIndex - 1].stubRoutine;
patchBuffer.link(failureCases1, lastProtoBegin);
patchBuffer.link(failureCases2, lastProtoBegin);
intptr_t successDest = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + patchOffsetGetByIdPutResult;
patchBuffer.link(success, reinterpret_cast<void*>(successDest));
structure->ref();
prototypeStructure->ref();
prototypeStructures->list[currentIndex].set(code, structure, prototypeStructure);
void* jumpLocation = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetGetByIdBranchToSlowCase;
Jump::patch(jumpLocation, code);
}
void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, CallFrame* callFrame)
{
ASSERT(count);
JumpList bucketsOfFail;
Jump baseObjectCheck = checkStructure(X86::eax, structure);
bucketsOfFail.append(baseObjectCheck);
Structure* currStructure = structure;
RefPtr<Structure>* chainEntries = chain->head();
JSObject* protoObject = 0;
for (unsigned i = 0; i < count; ++i) {
protoObject = asObject(currStructure->prototypeForLookup(callFrame));
currStructure = chainEntries[i].get();
Structure** prototypeStructureAddress = &(protoObject->m_structure);
#if PLATFORM(X86_64)
move(ImmPtr(currStructure), X86::ebx);
bucketsOfFail.append(jnePtr(X86::ebx, AbsoluteAddress(prototypeStructureAddress)));
#else
bucketsOfFail.append(jnePtr(AbsoluteAddress(prototypeStructureAddress), ImmPtr(currStructure)));
#endif
}
ASSERT(protoObject);
PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
loadPtr(protoPropertyStorage, X86::edx);
loadPtr(Address(X86::edx, cachedOffset * sizeof(JSValuePtr)), X86::eax);
Jump success = jump();
void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
PatchBuffer patchBuffer(code);
void* lastProtoBegin = prototypeStructures->list[currentIndex - 1].stubRoutine;
patchBuffer.link(bucketsOfFail, lastProtoBegin);
intptr_t successDest = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + patchOffsetGetByIdPutResult;
patchBuffer.link(success, reinterpret_cast<void*>(successDest));
structure->ref();
chain->ref();
prototypeStructures->list[currentIndex].set(code, structure, chain);
void* jumpLocation = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetGetByIdBranchToSlowCase;
Jump::patch(jumpLocation, code);
}
#endif
void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, void* returnAddress, CallFrame* callFrame)
{
#if USE(CTI_REPATCH_PIC)
Jump::patch(returnAddress, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_list));
ASSERT(count);
JumpList bucketsOfFail;
bucketsOfFail.append(checkStructure(X86::eax, structure));
Structure* currStructure = structure;
RefPtr<Structure>* chainEntries = chain->head();
JSObject* protoObject = 0;
for (unsigned i = 0; i < count; ++i) {
protoObject = asObject(currStructure->prototypeForLookup(callFrame));
currStructure = chainEntries[i].get();
Structure** prototypeStructureAddress = &(protoObject->m_structure);
#if PLATFORM(X86_64)
move(ImmPtr(currStructure), X86::ebx);
bucketsOfFail.append(jnePtr(X86::ebx, AbsoluteAddress(prototypeStructureAddress)));
#else
bucketsOfFail.append(jnePtr(AbsoluteAddress(prototypeStructureAddress), ImmPtr(currStructure)));
#endif
}
ASSERT(protoObject);
PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
loadPtr(protoPropertyStorage, X86::edx);
loadPtr(Address(X86::edx, cachedOffset * sizeof(JSValuePtr)), X86::eax);
Jump success = jump();
void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
PatchBuffer patchBuffer(code);
void* slowCaseBegin = reinterpret_cast<char*>(stubInfo->callReturnLocation) - patchOffsetGetByIdSlowCaseCall;
patchBuffer.link(bucketsOfFail, slowCaseBegin);
intptr_t successDest = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + patchOffsetGetByIdPutResult;
patchBuffer.link(success, reinterpret_cast<void*>(successDest));
stubInfo->stubRoutine = code;
void* jumpLocation = reinterpret_cast<char*>(stubInfo->hotPathBegin) + patchOffsetGetByIdBranchToSlowCase;
Jump::patch(jumpLocation, code);
#else
ASSERT(count);
JumpList bucketsOfFail;
bucketsOfFail.append(emitJumpIfNotJSCell(X86::eax));
bucketsOfFail.append(checkStructure(X86::eax, structure));
Structure* currStructure = structure;
RefPtr<Structure>* chainEntries = chain->head();
JSObject* protoObject = 0;
for (unsigned i = 0; i < count; ++i) {
protoObject = asObject(currStructure->prototypeForLookup(callFrame));
currStructure = chainEntries[i].get();
Structure** prototypeStructureAddress = &(protoObject->m_structure);
#if PLATFORM(X86_64)
move(ImmPtr(currStructure), X86::ebx);
bucketsOfFail.append(jnePtr(X86::ebx, AbsoluteAddress(prototypeStructureAddress)));
#else
bucketsOfFail.append(jnePtr(AbsoluteAddress(prototypeStructureAddress), ImmPtr(currStructure)));
#endif
}
ASSERT(protoObject);
PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
loadPtr(protoPropertyStorage, X86::edx);
loadPtr(Address(X86::edx, cachedOffset * sizeof(JSValuePtr)), X86::eax);
ret();
void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
patchBuffer.link(bucketsOfFail, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_fail));
stubInfo->stubRoutine = code;
Jump::patch(returnAddress, code);
#endif
}
void JIT::privateCompilePutByIdReplace(StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, void* returnAddress)
{
Jump failureCases1 = emitJumpIfNotJSCell(X86::eax);
Jump failureCases2 = checkStructure(X86::eax, structure);
loadPtr(Address(X86::eax, FIELD_OFFSET(JSObject, m_propertyStorage)), X86::eax);
storePtr(X86::edx, Address(X86::eax, cachedOffset * sizeof(JSValuePtr)));
ret();
void* code = m_assembler.executableCopy(m_codeBlock->executablePool());
PatchBuffer patchBuffer(code);
patchBuffer.link(failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_put_by_id_fail));
patchBuffer.link(failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_put_by_id_fail));
stubInfo->stubRoutine = code;
Jump::patch(returnAddress, code);
}
#endif
}
#endif // ENABLE(JIT)