📄 jitpropertyaccess.cpp
字号:
callTarget = call();#else push(Imm32(newStructure->propertyStorageCapacity())); push(Imm32(oldStructure->propertyStorageCapacity())); push(regT0); callTarget = call(); addPtr(Imm32(3 * sizeof(void*)), X86::esp);#endif emitGetJITStubArg(3, regT1); push(X86::ebx); } // Assumes m_refCount can be decremented easily, refcount decrement is safe as // codeblock should ensure oldStructure->m_refCount > 0 sub32(Imm32(1), AbsoluteAddress(oldStructure->addressOfCount())); add32(Imm32(1), AbsoluteAddress(newStructure->addressOfCount())); storePtr(ImmPtr(newStructure), Address(regT0, FIELD_OFFSET(JSCell, m_structure))); // write the value loadPtr(Address(regT0, FIELD_OFFSET(JSObject, m_propertyStorage)), regT0); storePtr(regT1, Address(regT0, cachedOffset * sizeof(JSValuePtr))); ret(); ASSERT(!failureCases.empty()); failureCases.link(this); restoreArgumentReferenceForTrampoline(); Call failureCall = tailRecursiveCall(); void* code = m_assembler.executableCopy(m_codeBlock->executablePool()); PatchBuffer patchBuffer(code); patchBuffer.link(failureCall, JITStubs::cti_op_put_by_id_fail); if (willNeedStorageRealloc) patchBuffer.link(callTarget, resizePropertyStorage); stubInfo->stubRoutine = patchBuffer.entry(); returnAddress.relinkCallerToFunction(code);}void JIT::patchGetByIdSelf(StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ProcessorReturnAddress returnAddress){ // We don't want to patch more than once - in future go to cti_op_get_by_id_generic. // Should probably go to JITStubs::cti_op_get_by_id_fail, but that doesn't do anything interesting right now. returnAddress.relinkCallerToFunction(JITStubs::cti_op_get_by_id_self_fail); // Patch the offset into the propoerty map to load from, then patch the Structure to look for. stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetGetByIdStructure).repatch(structure); stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetGetByIdPropertyMapOffset).repatch(cachedOffset * sizeof(JSValuePtr));}void JIT::patchPutByIdReplace(StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ProcessorReturnAddress returnAddress){ // We don't want to patch more than once - in future go to cti_op_put_by_id_generic. // Should probably go to JITStubs::cti_op_put_by_id_fail, but that doesn't do anything interesting right now. returnAddress.relinkCallerToFunction(JITStubs::cti_op_put_by_id_generic); // Patch the offset into the propoerty map to load from, then patch the Structure to look for. stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetPutByIdStructure).repatch(structure); stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset).repatch(cachedOffset * sizeof(JSValuePtr));}void JIT::privateCompilePatchGetArrayLength(ProcessorReturnAddress returnAddress){ StructureStubInfo* stubInfo = &m_codeBlock->getStubInfo(returnAddress); // We don't want to patch more than once - in future go to cti_op_put_by_id_generic. returnAddress.relinkCallerToFunction(JITStubs::cti_op_get_by_id_array_fail); // Check eax is an array Jump failureCases1 = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr)); // Checks out okay! - get the length from the storage loadPtr(Address(regT0, FIELD_OFFSET(JSArray, m_storage)), regT2); load32(Address(regT2, FIELD_OFFSET(ArrayStorage, m_length)), regT2); Jump failureCases2 = branch32(Above, regT2, Imm32(JSImmediate::maxImmediateInt)); emitFastArithIntToImmNoCheck(regT2, regT0); Jump success = jump(); void* code = m_assembler.executableCopy(m_codeBlock->executablePool()); PatchBuffer patchBuffer(code); // Use the patch information to link the failure cases back to the original slow case routine. CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall); patchBuffer.link(failureCases1, slowCaseBegin); patchBuffer.link(failureCases2, slowCaseBegin); // On success return back to the hot patch code, at a point it will perform the store to dest for us. patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult)); // Track the stub we have created so that it will be deleted later. CodeLocationLabel entryLabel = patchBuffer.entry(); stubInfo->stubRoutine = entryLabel; // Finally patch the jump to slow case back in the hot path to jump here instead. CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase); jumpLocation.relink(entryLabel);}void JIT::privateCompileGetByIdSelf(StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ProcessorReturnAddress returnAddress){ // Check eax is an object of the right Structure. Jump failureCases1 = emitJumpIfNotJSCell(regT0); Jump failureCases2 = checkStructure(regT0, structure); // Checks out okay! - getDirectOffset loadPtr(Address(regT0, FIELD_OFFSET(JSObject, m_propertyStorage)), regT0); loadPtr(Address(regT0, cachedOffset * sizeof(JSValuePtr)), regT0); ret(); Call failureCases1Call = makeTailRecursiveCall(failureCases1); Call failureCases2Call = makeTailRecursiveCall(failureCases2); void* code = m_assembler.executableCopy(m_codeBlock->executablePool()); PatchBuffer patchBuffer(code); patchBuffer.link(failureCases1Call, JITStubs::cti_op_get_by_id_self_fail); patchBuffer.link(failureCases2Call, JITStubs::cti_op_get_by_id_self_fail); stubInfo->stubRoutine = patchBuffer.entry(); returnAddress.relinkCallerToFunction(code);}void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, ProcessorReturnAddress returnAddress, CallFrame* callFrame){#if USE(CTI_REPATCH_PIC) // We don't want to patch more than once - in future go to cti_op_put_by_id_generic. returnAddress.relinkCallerToFunction(JITStubs::cti_op_get_by_id_proto_list); // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is // referencing the prototype object - let's speculatively load it's table nice and early!) JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame)); PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage; loadPtr(static_cast<void*>(protoPropertyStorage), regT1); // Check eax is an object of the right Structure. Jump failureCases1 = checkStructure(regT0, structure); // Check the prototype object's Structure had not changed. Structure** prototypeStructureAddress = &(protoObject->m_structure);#if PLATFORM(X86_64) move(ImmPtr(prototypeStructure), regT3); Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3);#else Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure));#endif // Checks out okay! - getDirectOffset loadPtr(Address(regT1, cachedOffset * sizeof(JSValuePtr)), regT0); Jump success = jump(); void* code = m_assembler.executableCopy(m_codeBlock->executablePool()); PatchBuffer patchBuffer(code); // Use the patch information to link the failure cases back to the original slow case routine. CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall); patchBuffer.link(failureCases1, slowCaseBegin); patchBuffer.link(failureCases2, slowCaseBegin); // On success return back to the hot patch code, at a point it will perform the store to dest for us. patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult)); // Track the stub we have created so that it will be deleted later. CodeLocationLabel entryLabel = patchBuffer.entry(); stubInfo->stubRoutine = entryLabel; // Finally patch the jump to slow case back in the hot path to jump here instead. CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase); jumpLocation.relink(entryLabel);#else // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is // referencing the prototype object - let's speculatively load it's table nice and early!) JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame)); PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage; loadPtr(protoPropertyStorage, regT1); // Check eax is an object of the right Structure. Jump failureCases1 = emitJumpIfNotJSCell(regT0); Jump failureCases2 = checkStructure(regT0, structure); // Check the prototype object's Structure had not changed. Structure** prototypeStructureAddress = &(protoObject->m_structure); Jump failureCases3 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure)); // Checks out okay! - getDirectOffset loadPtr(Address(regT1, cachedOffset * sizeof(JSValuePtr)), regT0); ret(); void* code = m_assembler.executableCopy(m_codeBlock->executablePool()); PatchBuffer patchBuffer(code); patchBuffer.link(failureCases1, JITStubs::cti_op_get_by_id_proto_fail); patchBuffer.link(failureCases2, JITStubs::cti_op_get_by_id_proto_fail); patchBuffer.link(failureCases3, JITStubs::cti_op_get_by_id_proto_fail); stubInfo->stubRoutine = patchBuffer.entry(); returnAddress.relinkCallerToFunction(code);#endif}#if USE(CTI_REPATCH_PIC)void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, size_t cachedOffset){ Jump failureCase = checkStructure(regT0, structure); loadPtr(Address(regT0, FIELD_OFFSET(JSObject, m_propertyStorage)), regT0); loadPtr(Address(regT0, cachedOffset * sizeof(JSValuePtr)), regT0); Jump success = jump(); void* code = m_assembler.executableCopy(m_codeBlock->executablePool()); ASSERT(code); PatchBuffer patchBuffer(code); // Use the patch information to link the failure cases back to the original slow case routine. CodeLocationLabel lastProtoBegin = polymorphicStructures->list[currentIndex - 1].stubRoutine; if (!lastProtoBegin) lastProtoBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall); patchBuffer.link(failureCase, lastProtoBegin); // On success return back to the hot patch code, at a point it will perform the store to dest for us. patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult)); CodeLocationLabel entryLabel = patchBuffer.entry(); structure->ref(); polymorphicStructures->list[currentIndex].set(entryLabel, structure);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -