diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2012-10-16 14:56:46 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2012-10-16 14:57:30 +0200 |
commit | b297e0fa5c217c9467033b7c8b46891a52870120 (patch) | |
tree | 43fc14689295e9e64f2719d05aad94e3049f6cd7 /Source/JavaScriptCore/jit | |
parent | 69d517dbfa69903d8593cc1737f0474b21e3251e (diff) | |
download | qtwebkit-b297e0fa5c217c9467033b7c8b46891a52870120.tar.gz |
Revert "Imported WebKit commit 0dc6cd75e1d4836eaffbb520be96fac4847cc9d2 (http://svn.webkit.org/repository/webkit/trunk@131300)"
This reverts commit 5466563f4b5b6b86523e3f89bb7f77e5b5270c78.
Caused OOM issues on some CI machines :(
Diffstat (limited to 'Source/JavaScriptCore/jit')
-rw-r--r-- | Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp | 1 | ||||
-rw-r--r-- | Source/JavaScriptCore/jit/HostCallReturnValue.h | 16 | ||||
-rw-r--r-- | Source/JavaScriptCore/jit/JIT.cpp | 39 | ||||
-rw-r--r-- | Source/JavaScriptCore/jit/JIT.h | 82 | ||||
-rw-r--r-- | Source/JavaScriptCore/jit/JITCall.cpp | 22 | ||||
-rw-r--r-- | Source/JavaScriptCore/jit/JITCall32_64.cpp | 34 | ||||
-rw-r--r-- | Source/JavaScriptCore/jit/JITCode.h | 6 | ||||
-rw-r--r-- | Source/JavaScriptCore/jit/JITInlineMethods.h | 83 | ||||
-rw-r--r-- | Source/JavaScriptCore/jit/JITOpcodes.cpp | 103 | ||||
-rw-r--r-- | Source/JavaScriptCore/jit/JITOpcodes32_64.cpp | 132 | ||||
-rw-r--r-- | Source/JavaScriptCore/jit/JITPropertyAccess.cpp | 557 | ||||
-rw-r--r-- | Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp | 192 | ||||
-rw-r--r-- | Source/JavaScriptCore/jit/JITStubs.cpp | 203 | ||||
-rw-r--r-- | Source/JavaScriptCore/jit/JITStubs.h | 20 | ||||
-rw-r--r-- | Source/JavaScriptCore/jit/JSInterfaceJIT.h | 2 | ||||
-rw-r--r-- | Source/JavaScriptCore/jit/SpecializedThunkJIT.h | 10 |
16 files changed, 328 insertions, 1174 deletions
diff --git a/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp b/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp index 7ee3e0497..2123f5a67 100644 --- a/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp +++ b/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp @@ -31,6 +31,7 @@ #include "CodeProfiling.h" #include <errno.h> +#include <sys/mman.h> #include <unistd.h> #include <wtf/MetaAllocator.h> #include <wtf/PageReservation.h> diff --git a/Source/JavaScriptCore/jit/HostCallReturnValue.h b/Source/JavaScriptCore/jit/HostCallReturnValue.h index 3f61179a3..0e17ca035 100644 --- a/Source/JavaScriptCore/jit/HostCallReturnValue.h +++ b/Source/JavaScriptCore/jit/HostCallReturnValue.h @@ -30,7 +30,10 @@ #include "MacroAssemblerCodeRef.h" #include <wtf/Platform.h> -#if ENABLE(JIT) +// Unfortunately this only works on GCC-like compilers. And it's currently only used +// by LLInt and DFG, which also are restricted to GCC-like compilers. We should +// probably fix that at some point. +#if COMPILER(GCC) && ENABLE(JIT) #if CALLING_CONVENTION_IS_STDCALL #define HOST_CALL_RETURN_VALUE_OPTION CDECL @@ -42,8 +45,6 @@ namespace JSC { extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValue() REFERENCED_FROM_ASM WTF_INTERNAL; -#if COMPILER(GCC) - // This is a public declaration only to convince CLANG not to elide it. extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValueWithExecState(ExecState*) REFERENCED_FROM_ASM WTF_INTERNAL; @@ -52,14 +53,15 @@ inline void initializeHostCallReturnValue() getHostCallReturnValueWithExecState(0); } +} + #else // COMPILER(GCC) +namespace JSC { inline void initializeHostCallReturnValue() { } +} #endif // COMPILER(GCC) -} // namespace JSC - -#endif // ENABLE(JIT) - #endif // HostCallReturnValue_h + diff --git a/Source/JavaScriptCore/jit/JIT.cpp b/Source/JavaScriptCore/jit/JIT.cpp index 143800d18..bf5ac88dd 100644 --- a/Source/JavaScriptCore/jit/JIT.cpp +++ b/Source/JavaScriptCore/jit/JIT.cpp @@ -78,7 +78,7 @@ JIT::JIT(JSGlobalData* globalData, CodeBlock* codeBlock) #if USE(JSVALUE32_64) , m_jumpTargetIndex(0) , m_mappedBytecodeOffset((unsigned)-1) - , m_mappedVirtualRegisterIndex(JSStack::ReturnPC) + , m_mappedVirtualRegisterIndex(RegisterFile::ReturnPC) , m_mappedTag((RegisterID)-1) , m_mappedPayload((RegisterID)-1) #else @@ -400,7 +400,6 @@ void JIT::privateCompileSlowCases() Instruction* instructionsBegin = m_codeBlock->instructions().begin(); m_propertyAccessInstructionIndex = 0; - m_byValInstructionIndex = 0; m_globalResolveInfoIndex = 0; m_callLinkInfoIndex = 0; @@ -607,8 +606,8 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck, JITCompilationEffo nop(); preserveReturnAddressAfterCall(regT2); - emitPutToCallFrameHeader(regT2, JSStack::ReturnPC); - emitPutImmediateToCallFrameHeader(m_codeBlock, JSStack::CodeBlock); + emitPutToCallFrameHeader(regT2, RegisterFile::ReturnPC); + emitPutImmediateToCallFrameHeader(m_codeBlock, RegisterFile::CodeBlock); Label beginLabel(this); @@ -617,7 +616,7 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck, JITCompilationEffo sampleInstruction(m_codeBlock->instructions().begin()); #endif - Jump stackCheck; + Jump registerFileCheck; if (m_codeBlock->codeType() == FunctionCode) { #if ENABLE(DFG_JIT) #if DFG_ENABLE(SUCCESS_STATS) @@ -647,7 +646,7 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck, JITCompilationEffo #endif addPtr(TrustedImm32(m_codeBlock->m_numCalleeRegisters * sizeof(Register)), callFrameRegister, regT1); - stackCheck = branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->stack().addressOfEnd()), regT1); + registerFileCheck = branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->registerFile().addressOfEnd()), regT1); } Label functionBody = label(); @@ -663,9 +662,9 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck, JITCompilationEffo Label arityCheck; if (m_codeBlock->codeType() == FunctionCode) { - stackCheck.link(this); + registerFileCheck.link(this); m_bytecodeOffset = 0; - JITStubCall(this, cti_stack_check).call(); + JITStubCall(this, cti_register_file_check).call(); #ifndef NDEBUG m_bytecodeOffset = (unsigned)-1; // Reset this, in order to guard its use with ASSERTs. #endif @@ -673,10 +672,10 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck, JITCompilationEffo arityCheck = label(); preserveReturnAddressAfterCall(regT2); - emitPutToCallFrameHeader(regT2, JSStack::ReturnPC); - emitPutImmediateToCallFrameHeader(m_codeBlock, JSStack::CodeBlock); + emitPutToCallFrameHeader(regT2, RegisterFile::ReturnPC); + emitPutImmediateToCallFrameHeader(m_codeBlock, RegisterFile::CodeBlock); - load32(payloadFor(JSStack::ArgumentCount), regT1); + load32(payloadFor(RegisterFile::ArgumentCount), regT1); branch32(AboveOrEqual, regT1, TrustedImm32(m_codeBlock->m_numParameters)).linkTo(beginLabel, this); m_bytecodeOffset = 0; @@ -716,8 +715,8 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck, JITCompilationEffo StringJumpTable::StringOffsetTable::iterator end = record.jumpTable.stringJumpTable->offsetTable.end(); for (StringJumpTable::StringOffsetTable::iterator it = record.jumpTable.stringJumpTable->offsetTable.begin(); it != end; ++it) { - unsigned offset = it->value.branchOffset; - it->value.ctiOffset = offset ? patchBuffer.locationOf(m_labels[bytecodeOffset + offset]) : record.jumpTable.stringJumpTable->ctiDefault; + unsigned offset = it->second.branchOffset; + it->second.ctiOffset = offset ? patchBuffer.locationOf(m_labels[bytecodeOffset + offset]) : record.jumpTable.stringJumpTable->ctiDefault; } } } @@ -739,20 +738,6 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck, JITCompilationEffo m_codeBlock->setNumberOfStructureStubInfos(m_propertyAccessCompilationInfo.size()); for (unsigned i = 0; i < m_propertyAccessCompilationInfo.size(); ++i) m_propertyAccessCompilationInfo[i].copyToStubInfo(m_codeBlock->structureStubInfo(i), patchBuffer); - m_codeBlock->setNumberOfByValInfos(m_byValCompilationInfo.size()); - for (unsigned i = 0; i < m_byValCompilationInfo.size(); ++i) { - CodeLocationJump badTypeJump = CodeLocationJump(patchBuffer.locationOf(m_byValCompilationInfo[i].badTypeJump)); - CodeLocationLabel doneTarget = patchBuffer.locationOf(m_byValCompilationInfo[i].doneTarget); - CodeLocationLabel slowPathTarget = patchBuffer.locationOf(m_byValCompilationInfo[i].slowPathTarget); - CodeLocationCall returnAddress = patchBuffer.locationOf(m_byValCompilationInfo[i].returnAddress); - - m_codeBlock->byValInfo(i) = ByValInfo( - m_byValCompilationInfo[i].bytecodeIndex, - badTypeJump, - m_byValCompilationInfo[i].arrayMode, - differenceBetweenCodePtr(badTypeJump, doneTarget), - differenceBetweenCodePtr(returnAddress, slowPathTarget)); - } m_codeBlock->setNumberOfCallLinkInfos(m_callStructureStubCompilationInfo.size()); for (unsigned i = 0; i < m_codeBlock->numberOfCallLinkInfos(); ++i) { CallLinkInfo& info = m_codeBlock->callLinkInfo(i); diff --git a/Source/JavaScriptCore/jit/JIT.h b/Source/JavaScriptCore/jit/JIT.h index 3e16972e2..150aae9ea 100644 --- a/Source/JavaScriptCore/jit/JIT.h +++ b/Source/JavaScriptCore/jit/JIT.h @@ -58,9 +58,9 @@ namespace JSC { class JIT; class JSPropertyNameIterator; class Interpreter; - class JSScope; - class JSStack; class Register; + class RegisterFile; + class JSScope; class StructureChain; struct CallLinkInfo; @@ -264,25 +264,6 @@ namespace JSC { void copyToStubInfo(StructureStubInfo& info, LinkBuffer &patchBuffer); }; - struct ByValCompilationInfo { - ByValCompilationInfo() { } - - ByValCompilationInfo(unsigned bytecodeIndex, MacroAssembler::PatchableJump badTypeJump, JITArrayMode arrayMode, MacroAssembler::Label doneTarget) - : bytecodeIndex(bytecodeIndex) - , badTypeJump(badTypeJump) - , arrayMode(arrayMode) - , doneTarget(doneTarget) - { - } - - unsigned bytecodeIndex; - MacroAssembler::PatchableJump badTypeJump; - JITArrayMode arrayMode; - MacroAssembler::Label doneTarget; - MacroAssembler::Label slowPathTarget; - MacroAssembler::Call returnAddress; - }; - struct StructureStubCompilationInfo { MacroAssembler::DataLabelPtr hotPathBegin; MacroAssembler::Call hotPathOther; @@ -367,20 +348,6 @@ namespace JSC { jit.m_bytecodeOffset = stubInfo->bytecodeIndex; jit.privateCompilePutByIdTransition(stubInfo, oldStructure, newStructure, cachedOffset, chain, returnAddress, direct); } - - static void compileGetByVal(JSGlobalData* globalData, CodeBlock* codeBlock, ByValInfo* byValInfo, ReturnAddressPtr returnAddress, JITArrayMode arrayMode) - { - JIT jit(globalData, codeBlock); - jit.m_bytecodeOffset = byValInfo->bytecodeIndex; - jit.privateCompileGetByVal(byValInfo, returnAddress, arrayMode); - } - - static void compilePutByVal(JSGlobalData* globalData, CodeBlock* codeBlock, ByValInfo* byValInfo, ReturnAddressPtr returnAddress, JITArrayMode arrayMode) - { - JIT jit(globalData, codeBlock); - jit.m_bytecodeOffset = byValInfo->bytecodeIndex; - jit.privateCompilePutByVal(byValInfo, returnAddress, arrayMode); - } static PassRefPtr<ExecutableMemoryHandle> compileCTIMachineTrampolines(JSGlobalData* globalData, TrampolineStructure *trampolines) { @@ -412,10 +379,6 @@ namespace JSC { static void compilePatchGetArrayLength(JSGlobalData* globalData, CodeBlock* codeBlock, ReturnAddressPtr returnAddress) { JIT jit(globalData, codeBlock); -#if ENABLE(DFG_JIT) - // Force profiling to be enabled during stub generation. - jit.m_canBeOptimized = true; -#endif // ENABLE(DFG_JIT) return jit.privateCompilePatchGetArrayLength(returnAddress); } @@ -434,9 +397,6 @@ namespace JSC { void privateCompileGetByIdChainList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, StructureChain*, size_t count, const Identifier&, const PropertySlot&, PropertyOffset cachedOffset, CallFrame*); void privateCompileGetByIdChain(StructureStubInfo*, Structure*, StructureChain*, size_t count, const Identifier&, const PropertySlot&, PropertyOffset cachedOffset, ReturnAddressPtr, CallFrame*); void privateCompilePutByIdTransition(StructureStubInfo*, Structure*, Structure*, PropertyOffset cachedOffset, StructureChain*, ReturnAddressPtr, bool direct); - - void privateCompileGetByVal(ByValInfo*, ReturnAddressPtr, JITArrayMode); - void privateCompilePutByVal(ByValInfo*, ReturnAddressPtr, JITArrayMode); PassRefPtr<ExecutableMemoryHandle> privateCompileCTIMachineTrampolines(JSGlobalData*, TrampolineStructure*); Label privateCompileCTINativeCall(JSGlobalData*, bool isConstruct = false); @@ -474,7 +434,7 @@ namespace JSC { void emitWriteBarrier(RegisterID owner, RegisterID valueTag, RegisterID scratch, RegisterID scratch2, WriteBarrierMode, WriteBarrierUseKind); void emitWriteBarrier(JSCell* owner, RegisterID value, RegisterID scratch, WriteBarrierMode, WriteBarrierUseKind); - template<typename ClassType, MarkedBlock::DestructorType, typename StructureType> void emitAllocateBasicJSObject(StructureType, RegisterID result, RegisterID storagePtr); + template<typename ClassType, bool destructor, typename StructureType> void emitAllocateBasicJSObject(StructureType, RegisterID result, RegisterID storagePtr); void emitAllocateBasicStorage(size_t, ptrdiff_t offsetFromBase, RegisterID result); template<typename T> void emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID storagePtr); void emitAllocateJSArray(unsigned valuesRegister, unsigned length, RegisterID cellResult, RegisterID storageResult, RegisterID storagePtr, RegisterID scratch); @@ -492,27 +452,7 @@ namespace JSC { void emitArrayProfilingSite(RegisterID structureAndIndexingType, RegisterID scratch, ArrayProfile*); void emitArrayProfilingSiteForBytecodeIndex(RegisterID structureAndIndexingType, RegisterID scratch, unsigned bytecodeIndex); void emitArrayProfileStoreToHoleSpecialCase(ArrayProfile*); - - JITArrayMode chooseArrayMode(ArrayProfile*); - - // Property is in regT1, base is in regT0. regT2 contains indexing type. - // Property is int-checked and zero extended. Base is cell checked. - // Structure is already profiled. Returns the slow cases. Fall-through - // case contains result in regT0, and it is not yet profiled. - JumpList emitContiguousGetByVal(Instruction*, PatchableJump& badType); - JumpList emitArrayStorageGetByVal(Instruction*, PatchableJump& badType); - JumpList emitIntTypedArrayGetByVal(Instruction*, PatchableJump& badType, const TypedArrayDescriptor&, size_t elementSize, TypedArraySignedness); - JumpList emitFloatTypedArrayGetByVal(Instruction*, PatchableJump& badType, const TypedArrayDescriptor&, size_t elementSize); - - // Property is in regT0, base is in regT0. regT2 contains indecing type. - // The value to store is not yet loaded. Property is int-checked and - // zero-extended. Base is cell checked. Structure is already profiled. - // returns the slow cases. - JumpList emitContiguousPutByVal(Instruction*, PatchableJump& badType); - JumpList emitArrayStoragePutByVal(Instruction*, PatchableJump& badType); - JumpList emitIntTypedArrayPutByVal(Instruction*, PatchableJump& badType, const TypedArrayDescriptor&, size_t elementSize, TypedArraySignedness, TypedArrayRounding); - JumpList emitFloatTypedArrayPutByVal(Instruction*, PatchableJump& badType, const TypedArrayDescriptor&, size_t elementSize); - + enum FinalObjectMode { MayBeFinal, KnownNotFinal }; #if USE(JSVALUE32_64) @@ -838,12 +778,12 @@ namespace JSC { void emitInitRegister(unsigned dst); - void emitPutToCallFrameHeader(RegisterID from, JSStack::CallFrameHeaderEntry); - void emitPutCellToCallFrameHeader(RegisterID from, JSStack::CallFrameHeaderEntry); - void emitPutIntToCallFrameHeader(RegisterID from, JSStack::CallFrameHeaderEntry); - void emitPutImmediateToCallFrameHeader(void* value, JSStack::CallFrameHeaderEntry); - void emitGetFromCallFrameHeaderPtr(JSStack::CallFrameHeaderEntry, RegisterID to, RegisterID from = callFrameRegister); - void emitGetFromCallFrameHeader32(JSStack::CallFrameHeaderEntry, RegisterID to, RegisterID from = callFrameRegister); + void emitPutToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry); + void emitPutCellToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry); + void emitPutIntToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry); + void emitPutImmediateToCallFrameHeader(void* value, RegisterFile::CallFrameHeaderEntry entry); + void emitGetFromCallFrameHeaderPtr(RegisterFile::CallFrameHeaderEntry entry, RegisterID to, RegisterID from = callFrameRegister); + void emitGetFromCallFrameHeader32(RegisterFile::CallFrameHeaderEntry entry, RegisterID to, RegisterID from = callFrameRegister); JSValue getConstantOperand(unsigned src); bool isOperandConstantImmediateInt(unsigned src); @@ -930,7 +870,6 @@ namespace JSC { Vector<CallRecord> m_calls; Vector<Label> m_labels; Vector<PropertyStubCompilationInfo> m_propertyAccessCompilationInfo; - Vector<ByValCompilationInfo> m_byValCompilationInfo; Vector<StructureStubCompilationInfo> m_callStructureStubCompilationInfo; Vector<MethodCallCompilationInfo> m_methodCallCompilationInfo; Vector<JumpTable> m_jmpTable; @@ -940,7 +879,6 @@ namespace JSC { Vector<SwitchRecord> m_switches; unsigned m_propertyAccessInstructionIndex; - unsigned m_byValInstructionIndex; unsigned m_globalResolveInfoIndex; unsigned m_callLinkInfoIndex; diff --git a/Source/JavaScriptCore/jit/JITCall.cpp b/Source/JavaScriptCore/jit/JITCall.cpp index 1de877daa..b5f4f8278 100644 --- a/Source/JavaScriptCore/jit/JITCall.cpp +++ b/Source/JavaScriptCore/jit/JITCall.cpp @@ -74,20 +74,20 @@ void JIT::compileLoadVarargs(Instruction* instruction) emitGetVirtualRegister(arguments, regT0); slowCase.append(branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(JSValue())))); - emitGetFromCallFrameHeader32(JSStack::ArgumentCount, regT0); + emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0); slowCase.append(branch32(Above, regT0, TrustedImm32(Arguments::MaxArguments + 1))); // regT0: argumentCountIncludingThis move(regT0, regT1); - add32(TrustedImm32(firstFreeRegister + JSStack::CallFrameHeaderSize), regT1); + add32(TrustedImm32(firstFreeRegister + RegisterFile::CallFrameHeaderSize), regT1); lshift32(TrustedImm32(3), regT1); addPtr(callFrameRegister, regT1); // regT1: newCallFrame - slowCase.append(branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->stack().addressOfEnd()), regT1)); + slowCase.append(branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->registerFile().addressOfEnd()), regT1)); // Initialize ArgumentCount. - store32(regT0, Address(regT1, JSStack::ArgumentCount * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload))); + store32(regT0, Address(regT1, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload))); // Initialize 'this'. emitGetVirtualRegister(thisValue, regT2); @@ -125,7 +125,7 @@ void JIT::compileCallEval() JITStubCall stubCall(this, cti_op_call_eval); // Initializes ScopeChain; ReturnPC; CodeBlock. stubCall.call(); addSlowCase(branchPtr(Equal, regT0, TrustedImmPtr(JSValue::encode(JSValue())))); - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, callFrameRegister); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister); sampleCodeBlock(m_codeBlock); } @@ -134,7 +134,7 @@ void JIT::compileCallEvalSlowCase(Vector<SlowCaseEntry>::iterator& iter) { linkSlowCase(iter); - emitGetFromCallFrameHeaderPtr(JSStack::Callee, regT0); + emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT0); emitNakedCall(m_globalData->jitStubs->ctiVirtualCall()); sampleCodeBlock(m_codeBlock); @@ -173,14 +173,14 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca } addPtr(TrustedImm32(registerOffset * sizeof(Register)), callFrameRegister, regT1); - store32(TrustedImm32(argCount), Address(regT1, JSStack::ArgumentCount * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload))); + store32(TrustedImm32(argCount), Address(regT1, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload))); } // regT1 holds newCallFrame with ArgumentCount initialized. - store32(TrustedImm32(instruction - m_codeBlock->instructions().begin()), Address(callFrameRegister, JSStack::ArgumentCount * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag))); + store32(TrustedImm32(instruction - m_codeBlock->instructions().begin()), Address(callFrameRegister, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag))); emitGetVirtualRegister(callee, regT0); // regT0 holds callee. - storePtr(callFrameRegister, Address(regT1, JSStack::CallerFrame * static_cast<int>(sizeof(Register)))); - storePtr(regT0, Address(regT1, JSStack::Callee * static_cast<int>(sizeof(Register)))); + storePtr(callFrameRegister, Address(regT1, RegisterFile::CallerFrame * static_cast<int>(sizeof(Register)))); + storePtr(regT0, Address(regT1, RegisterFile::Callee * static_cast<int>(sizeof(Register)))); move(regT1, callFrameRegister); if (opcodeID == op_call_eval) { @@ -201,7 +201,7 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca m_callStructureStubCompilationInfo[callLinkInfoIndex].bytecodeIndex = m_bytecodeOffset; loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scope)), regT1); - emitPutToCallFrameHeader(regT1, JSStack::ScopeChain); + emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain); m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall(); sampleCodeBlock(m_codeBlock); diff --git a/Source/JavaScriptCore/jit/JITCall32_64.cpp b/Source/JavaScriptCore/jit/JITCall32_64.cpp index ad827cdf9..09727d532 100644 --- a/Source/JavaScriptCore/jit/JITCall32_64.cpp +++ b/Source/JavaScriptCore/jit/JITCall32_64.cpp @@ -59,8 +59,8 @@ void JIT::emit_op_ret(Instruction* currentInstruction) unsigned dst = currentInstruction[1].u.operand; emitLoad(dst, regT1, regT0); - emitGetFromCallFrameHeaderPtr(JSStack::ReturnPC, regT2); - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, callFrameRegister); + emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT2); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister); restoreReturnAddressBeforeReturn(regT2); ret(); @@ -76,8 +76,8 @@ void JIT::emit_op_ret_object_or_this(Instruction* currentInstruction) loadPtr(Address(regT0, JSCell::structureOffset()), regT2); Jump notObject = emitJumpIfNotObject(regT2); - emitGetFromCallFrameHeaderPtr(JSStack::ReturnPC, regT2); - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, callFrameRegister); + emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT2); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister); restoreReturnAddressBeforeReturn(regT2); ret(); @@ -86,8 +86,8 @@ void JIT::emit_op_ret_object_or_this(Instruction* currentInstruction) notObject.link(this); emitLoad(thisReg, regT1, regT0); - emitGetFromCallFrameHeaderPtr(JSStack::ReturnPC, regT2); - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, callFrameRegister); + emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT2); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister); restoreReturnAddressBeforeReturn(regT2); ret(); @@ -149,20 +149,20 @@ void JIT::compileLoadVarargs(Instruction* instruction) emitLoadTag(arguments, regT1); slowCase.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::EmptyValueTag))); - load32(payloadFor(JSStack::ArgumentCount), regT2); + load32(payloadFor(RegisterFile::ArgumentCount), regT2); slowCase.append(branch32(Above, regT2, TrustedImm32(Arguments::MaxArguments + 1))); // regT2: argumentCountIncludingThis move(regT2, regT3); - add32(TrustedImm32(firstFreeRegister + JSStack::CallFrameHeaderSize), regT3); + add32(TrustedImm32(firstFreeRegister + RegisterFile::CallFrameHeaderSize), regT3); lshift32(TrustedImm32(3), regT3); addPtr(callFrameRegister, regT3); // regT3: newCallFrame - slowCase.append(branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->stack().addressOfEnd()), regT3)); + slowCase.append(branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->registerFile().addressOfEnd()), regT3)); // Initialize ArgumentCount. - store32(regT2, payloadFor(JSStack::ArgumentCount, regT3)); + store32(regT2, payloadFor(RegisterFile::ArgumentCount, regT3)); // Initialize 'this'. emitLoad(thisValue, regT1, regT0); @@ -202,7 +202,7 @@ void JIT::compileCallEval() JITStubCall stubCall(this, cti_op_call_eval); // Initializes ScopeChain; ReturnPC; CodeBlock. stubCall.call(); addSlowCase(branch32(Equal, regT1, TrustedImm32(JSValue::EmptyValueTag))); - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, callFrameRegister); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister); sampleCodeBlock(m_codeBlock); } @@ -211,7 +211,7 @@ void JIT::compileCallEvalSlowCase(Vector<SlowCaseEntry>::iterator& iter) { linkSlowCase(iter); - emitLoad(JSStack::Callee, regT1, regT0); + emitLoad(RegisterFile::Callee, regT1, regT0); emitNakedCall(m_globalData->jitStubs->ctiVirtualCall()); sampleCodeBlock(m_codeBlock); @@ -251,14 +251,14 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca addPtr(TrustedImm32(registerOffset * sizeof(Register)), callFrameRegister, regT3); - store32(TrustedImm32(argCount), payloadFor(JSStack::ArgumentCount, regT3)); + store32(TrustedImm32(argCount), payloadFor(RegisterFile::ArgumentCount, regT3)); } // regT3 holds newCallFrame with ArgumentCount initialized. - storePtr(TrustedImmPtr(instruction), tagFor(JSStack::ArgumentCount, callFrameRegister)); + storePtr(TrustedImmPtr(instruction), tagFor(RegisterFile::ArgumentCount, callFrameRegister)); emitLoad(callee, regT1, regT0); // regT1, regT0 holds callee. - storePtr(callFrameRegister, Address(regT3, JSStack::CallerFrame * static_cast<int>(sizeof(Register)))); - emitStore(JSStack::Callee, regT1, regT0, regT3); + storePtr(callFrameRegister, Address(regT3, RegisterFile::CallerFrame * static_cast<int>(sizeof(Register)))); + emitStore(RegisterFile::Callee, regT1, regT0, regT3); move(regT3, callFrameRegister); if (opcodeID == op_call_eval) { @@ -281,7 +281,7 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca m_callStructureStubCompilationInfo[callLinkInfoIndex].bytecodeIndex = m_bytecodeOffset; loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scope)), regT1); - emitPutCellToCallFrameHeader(regT1, JSStack::ScopeChain); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall(); sampleCodeBlock(m_codeBlock); diff --git a/Source/JavaScriptCore/jit/JITCode.h b/Source/JavaScriptCore/jit/JITCode.h index 93fa88a23..e39b4f98d 100644 --- a/Source/JavaScriptCore/jit/JITCode.h +++ b/Source/JavaScriptCore/jit/JITCode.h @@ -38,7 +38,7 @@ namespace JSC { #if ENABLE(JIT) class JSGlobalData; - class JSStack; + class RegisterFile; #endif class JITCode { @@ -129,9 +129,9 @@ namespace JSC { #if ENABLE(JIT) // Execute the code! - inline JSValue execute(JSStack* stack, CallFrame* callFrame, JSGlobalData* globalData) + inline JSValue execute(RegisterFile* registerFile, CallFrame* callFrame, JSGlobalData* globalData) { - JSValue result = JSValue::decode(ctiTrampoline(m_ref.code().executableAddress(), stack, callFrame, 0, 0, globalData)); + JSValue result = JSValue::decode(ctiTrampoline(m_ref.code().executableAddress(), registerFile, callFrame, 0, 0, globalData)); return globalData->exception ? jsNull() : result; } #endif diff --git a/Source/JavaScriptCore/jit/JITInlineMethods.h b/Source/JavaScriptCore/jit/JITInlineMethods.h index a7aecd3e8..ed63ad348 100644 --- a/Source/JavaScriptCore/jit/JITInlineMethods.h +++ b/Source/JavaScriptCore/jit/JITInlineMethods.h @@ -50,12 +50,12 @@ ALWAYS_INLINE JSValue JIT::getConstantOperand(unsigned src) return m_codeBlock->getConstant(src); } -ALWAYS_INLINE void JIT::emitPutToCallFrameHeader(RegisterID from, JSStack::CallFrameHeaderEntry entry) +ALWAYS_INLINE void JIT::emitPutToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry) { storePtr(from, payloadFor(entry, callFrameRegister)); } -ALWAYS_INLINE void JIT::emitPutCellToCallFrameHeader(RegisterID from, JSStack::CallFrameHeaderEntry entry) +ALWAYS_INLINE void JIT::emitPutCellToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry) { #if USE(JSVALUE32_64) store32(TrustedImm32(JSValue::CellTag), tagFor(entry, callFrameRegister)); @@ -63,18 +63,18 @@ ALWAYS_INLINE void JIT::emitPutCellToCallFrameHeader(RegisterID from, JSStack::C storePtr(from, payloadFor(entry, callFrameRegister)); } -ALWAYS_INLINE void JIT::emitPutIntToCallFrameHeader(RegisterID from, JSStack::CallFrameHeaderEntry entry) +ALWAYS_INLINE void JIT::emitPutIntToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry) { store32(TrustedImm32(Int32Tag), intTagFor(entry, callFrameRegister)); store32(from, intPayloadFor(entry, callFrameRegister)); } -ALWAYS_INLINE void JIT::emitPutImmediateToCallFrameHeader(void* value, JSStack::CallFrameHeaderEntry entry) +ALWAYS_INLINE void JIT::emitPutImmediateToCallFrameHeader(void* value, RegisterFile::CallFrameHeaderEntry entry) { storePtr(TrustedImmPtr(value), Address(callFrameRegister, entry * sizeof(Register))); } -ALWAYS_INLINE void JIT::emitGetFromCallFrameHeaderPtr(JSStack::CallFrameHeaderEntry entry, RegisterID to, RegisterID from) +ALWAYS_INLINE void JIT::emitGetFromCallFrameHeaderPtr(RegisterFile::CallFrameHeaderEntry entry, RegisterID to, RegisterID from) { loadPtr(Address(from, entry * sizeof(Register)), to); #if USE(JSVALUE64) @@ -101,7 +101,7 @@ ALWAYS_INLINE void JIT::emitLoadCharacterString(RegisterID src, RegisterID dst, cont8Bit.link(this); } -ALWAYS_INLINE void JIT::emitGetFromCallFrameHeader32(JSStack::CallFrameHeaderEntry entry, RegisterID to, RegisterID from) +ALWAYS_INLINE void JIT::emitGetFromCallFrameHeader32(RegisterFile::CallFrameHeaderEntry entry, RegisterID to, RegisterID from) { load32(Address(from, entry * sizeof(Register)), to); #if USE(JSVALUE64) @@ -265,9 +265,9 @@ ALWAYS_INLINE void JIT::updateTopCallFrame() ASSERT(static_cast<int>(m_bytecodeOffset) >= 0); if (m_bytecodeOffset) { #if USE(JSVALUE32_64) - storePtr(TrustedImmPtr(m_codeBlock->instructions().begin() + m_bytecodeOffset + 1), intTagFor(JSStack::ArgumentCount)); + storePtr(TrustedImmPtr(m_codeBlock->instructions().begin() + m_bytecodeOffset + 1), intTagFor(RegisterFile::ArgumentCount)); #else - store32(TrustedImm32(m_bytecodeOffset + 1), intTagFor(JSStack::ArgumentCount)); + store32(TrustedImm32(m_bytecodeOffset + 1), intTagFor(RegisterFile::ArgumentCount)); #endif } storePtr(callFrameRegister, &m_globalData->topCallFrame); @@ -405,16 +405,13 @@ ALWAYS_INLINE bool JIT::isOperandConstantImmediateChar(unsigned src) return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isString() && asString(getConstantOperand(src).asCell())->length() == 1; } -template <typename ClassType, MarkedBlock::DestructorType destructorType, typename StructureType> inline void JIT::emitAllocateBasicJSObject(StructureType structure, RegisterID result, RegisterID storagePtr) +template <typename ClassType, bool destructor, typename StructureType> inline void JIT::emitAllocateBasicJSObject(StructureType structure, RegisterID result, RegisterID storagePtr) { - size_t size = ClassType::allocationSize(INLINE_STORAGE_CAPACITY); MarkedAllocator* allocator = 0; - if (destructorType == MarkedBlock::Normal) - allocator = &m_globalData->heap.allocatorForObjectWithNormalDestructor(size); - else if (destructorType == MarkedBlock::ImmortalStructure) - allocator = &m_globalData->heap.allocatorForObjectWithImmortalStructureDestructor(size); + if (destructor) + allocator = &m_globalData->heap.allocatorForObjectWithDestructor(sizeof(ClassType)); else - allocator = &m_globalData->heap.allocatorForObjectWithoutDestructor(size); + allocator = &m_globalData->heap.allocatorForObjectWithoutDestructor(sizeof(ClassType)); loadPtr(&allocator->m_freeList.head, result); addSlowCase(branchTestPtr(Zero, result)); @@ -431,7 +428,7 @@ template <typename ClassType, MarkedBlock::DestructorType destructorType, typena template <typename T> inline void JIT::emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID scratch) { - emitAllocateBasicJSObject<JSFinalObject, MarkedBlock::None, T>(structure, result, scratch); + emitAllocateBasicJSObject<JSFinalObject, false, T>(structure, result, scratch); } inline void JIT::emitAllocateBasicStorage(size_t size, ptrdiff_t offsetFromBase, RegisterID result) @@ -448,24 +445,23 @@ inline void JIT::emitAllocateBasicStorage(size_t size, ptrdiff_t offsetFromBase, inline void JIT::emitAllocateJSArray(unsigned valuesRegister, unsigned length, RegisterID cellResult, RegisterID storageResult, RegisterID storagePtr, RegisterID scratch) { - unsigned initialLength = std::max(length, BASE_VECTOR_LEN); - size_t initialStorage = Butterfly::totalSize(0, 0, true, initialLength * sizeof(EncodedJSValue)); - - loadPtr(m_codeBlock->globalObject()->addressOfArrayStructure(), scratch); - load8(Address(scratch, Structure::indexingTypeOffset()), storagePtr); - and32(TrustedImm32(IndexingShapeMask), storagePtr); - addSlowCase(branch32(NotEqual, storagePtr, TrustedImm32(ContiguousShape))); + unsigned initialLength = std::max(length, 4U); + size_t initialStorage = Butterfly::totalSize(0, 0, true, ArrayStorage::sizeFor(initialLength)); // We allocate the backing store first to ensure that garbage collection // doesn't happen during JSArray initialization. emitAllocateBasicStorage(initialStorage, sizeof(IndexingHeader), storageResult); // Allocate the cell for the array. - emitAllocateBasicJSObject<JSArray, MarkedBlock::None>(scratch, cellResult, storagePtr); + loadPtr(m_codeBlock->globalObject()->addressOfArrayStructure(), scratch); + emitAllocateBasicJSObject<JSArray, false>(scratch, cellResult, storagePtr); - // Store all the necessary info in the indexing header. - store32(Imm32(length), Address(storageResult, Butterfly::offsetOfPublicLength())); - store32(Imm32(initialLength), Address(storageResult, Butterfly::offsetOfVectorLength())); + // Store all the necessary info in the ArrayStorage. + store32(Imm32(length), Address(storageResult, ArrayStorage::lengthOffset())); + store32(Imm32(length), Address(storageResult, ArrayStorage::numValuesInVectorOffset())); + store32(Imm32(initialLength), Address(storageResult, ArrayStorage::vectorLengthOffset())); + store32(TrustedImm32(0), Address(storageResult, ArrayStorage::indexBiasOffset())); + storePtr(TrustedImmPtr(0), Address(storageResult, ArrayStorage::sparseMapOffset())); // Store the newly allocated ArrayStorage. storePtr(storageResult, Address(cellResult, JSObject::butterflyOffset())); @@ -474,12 +470,12 @@ inline void JIT::emitAllocateJSArray(unsigned valuesRegister, unsigned length, R for (unsigned i = 0; i < length; i++) { #if USE(JSVALUE64) loadPtr(Address(callFrameRegister, (valuesRegister + i) * sizeof(Register)), storagePtr); - storePtr(storagePtr, Address(storageResult, sizeof(WriteBarrier<Unknown>) * i)); + storePtr(storagePtr, Address(storageResult, ArrayStorage::vectorOffset() + sizeof(WriteBarrier<Unknown>) * i)); #else load32(Address(callFrameRegister, (valuesRegister + i) * sizeof(Register)), storagePtr); - store32(storagePtr, Address(storageResult, sizeof(WriteBarrier<Unknown>) * i)); + store32(storagePtr, Address(storageResult, ArrayStorage::vectorOffset() + sizeof(WriteBarrier<Unknown>) * i)); load32(Address(callFrameRegister, (valuesRegister + i) * sizeof(Register) + sizeof(uint32_t)), storagePtr); - store32(storagePtr, Address(storageResult, sizeof(WriteBarrier<Unknown>) * i + sizeof(uint32_t))); + store32(storagePtr, Address(storageResult, ArrayStorage::vectorOffset() + sizeof(WriteBarrier<Unknown>) * i + sizeof(uint32_t))); #endif } } @@ -563,29 +559,10 @@ inline void JIT::emitArrayProfilingSiteForBytecodeIndex(RegisterID structureAndI inline void JIT::emitArrayProfileStoreToHoleSpecialCase(ArrayProfile* arrayProfile) { -#if ENABLE(VALUE_PROFILER) + if (!canBeOptimized()) + return; + store8(TrustedImm32(1), arrayProfile->addressOfMayStoreToHole()); -#else - UNUSED_PARAM(arrayProfile); -#endif -} - -static inline bool arrayProfileSaw(ArrayProfile* profile, IndexingType capability) -{ -#if ENABLE(VALUE_PROFILER) - return !!(profile->observedArrayModes() & (asArrayModes(NonArray | capability) | asArrayModes(ArrayClass | capability))); -#else - UNUSED_PARAM(profile); - UNUSED_PARAM(capability); - return false; -#endif -} - -inline JITArrayMode JIT::chooseArrayMode(ArrayProfile* profile) -{ - if (arrayProfileSaw(profile, ArrayStorageShape)) - return JITArrayStorage; - return JITContiguous; } #if USE(JSVALUE32_64) @@ -778,7 +755,7 @@ inline void JIT::unmap(RegisterID registerID) inline void JIT::unmap() { m_mappedBytecodeOffset = (unsigned)-1; - m_mappedVirtualRegisterIndex = JSStack::ReturnPC; + m_mappedVirtualRegisterIndex = RegisterFile::ReturnPC; m_mappedTag = (RegisterID)-1; m_mappedPayload = (RegisterID)-1; } diff --git a/Source/JavaScriptCore/jit/JITOpcodes.cpp b/Source/JavaScriptCore/jit/JITOpcodes.cpp index 33db1d44f..3b7f38dc7 100644 --- a/Source/JavaScriptCore/jit/JITOpcodes.cpp +++ b/Source/JavaScriptCore/jit/JITOpcodes.cpp @@ -76,11 +76,11 @@ PassRefPtr<ExecutableMemoryHandle> JIT::privateCompileCTIMachineTrampolines(JSGl // Finish canonical initialization before JS function call. loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scope)), regT1); - emitPutCellToCallFrameHeader(regT1, JSStack::ScopeChain); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); // Also initialize ReturnPC for use by lazy linking and exceptions. preserveReturnAddressAfterCall(regT3); - emitPutToCallFrameHeader(regT3, JSStack::ReturnPC); + emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC); storePtr(callFrameRegister, &m_globalData->topCallFrame); restoreArgumentReference(); @@ -96,11 +96,11 @@ PassRefPtr<ExecutableMemoryHandle> JIT::privateCompileCTIMachineTrampolines(JSGl // Finish canonical initialization before JS function call. loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scope)), regT1); - emitPutCellToCallFrameHeader(regT1, JSStack::ScopeChain); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); // Also initialize ReturnPC for use by lazy linking and exeptions. preserveReturnAddressAfterCall(regT3); - emitPutToCallFrameHeader(regT3, JSStack::ReturnPC); + emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC); storePtr(callFrameRegister, &m_globalData->topCallFrame); restoreArgumentReference(); @@ -116,7 +116,7 @@ PassRefPtr<ExecutableMemoryHandle> JIT::privateCompileCTIMachineTrampolines(JSGl // Finish canonical initialization before JS function call. loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scope)), regT1); - emitPutCellToCallFrameHeader(regT1, JSStack::ScopeChain); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2); Jump hasCodeBlock1 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForCall)), TrustedImm32(0)); @@ -139,7 +139,7 @@ PassRefPtr<ExecutableMemoryHandle> JIT::privateCompileCTIMachineTrampolines(JSGl // Finish canonical initialization before JS function call. loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scope)), regT1); - emitPutCellToCallFrameHeader(regT1, JSStack::ScopeChain); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2); Jump hasCodeBlock2 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForConstruct)), TrustedImm32(0)); @@ -156,37 +156,37 @@ PassRefPtr<ExecutableMemoryHandle> JIT::privateCompileCTIMachineTrampolines(JSGl callSlowCase.link(this); // Finish canonical initialization before JS function call. - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, regT2); - emitGetFromCallFrameHeaderPtr(JSStack::ScopeChain, regT2, regT2); - emitPutCellToCallFrameHeader(regT2, JSStack::ScopeChain); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2); + emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2, regT2); + emitPutCellToCallFrameHeader(regT2, RegisterFile::ScopeChain); // Also initialize ReturnPC and CodeBlock, like a JS function would. preserveReturnAddressAfterCall(regT3); - emitPutToCallFrameHeader(regT3, JSStack::ReturnPC); - emitPutImmediateToCallFrameHeader(0, JSStack::CodeBlock); + emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC); + emitPutImmediateToCallFrameHeader(0, RegisterFile::CodeBlock); storePtr(callFrameRegister, &m_globalData->topCallFrame); restoreArgumentReference(); Call callCallNotJSFunction = call(); - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, callFrameRegister); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister); restoreReturnAddressBeforeReturn(regT3); ret(); constructSlowCase.link(this); // Finish canonical initialization before JS function call. - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, regT2); - emitGetFromCallFrameHeaderPtr(JSStack::ScopeChain, regT2, regT2); - emitPutCellToCallFrameHeader(regT2, JSStack::ScopeChain); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2); + emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2, regT2); + emitPutCellToCallFrameHeader(regT2, RegisterFile::ScopeChain); // Also initialize ReturnPC and CodeBlock, like a JS function would. preserveReturnAddressAfterCall(regT3); - emitPutToCallFrameHeader(regT3, JSStack::ReturnPC); - emitPutImmediateToCallFrameHeader(0, JSStack::CodeBlock); + emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC); + emitPutImmediateToCallFrameHeader(0, RegisterFile::CodeBlock); storePtr(callFrameRegister, &m_globalData->topCallFrame); restoreArgumentReference(); Call callConstructNotJSFunction = call(); - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, callFrameRegister); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister); restoreReturnAddressBeforeReturn(regT3); ret(); @@ -231,18 +231,18 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon Label nativeCallThunk = align(); - emitPutImmediateToCallFrameHeader(0, JSStack::CodeBlock); + emitPutImmediateToCallFrameHeader(0, RegisterFile::CodeBlock); storePtr(callFrameRegister, &m_globalData->topCallFrame); #if CPU(X86_64) // Load caller frame's scope chain into this callframe so that whatever we call can // get to its global data. - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, regT0); - emitGetFromCallFrameHeaderPtr(JSStack::ScopeChain, regT1, regT0); - emitPutCellToCallFrameHeader(regT1, JSStack::ScopeChain); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT0); + emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT0); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); peek(regT1); - emitPutToCallFrameHeader(regT1, JSStack::ReturnPC); + emitPutToCallFrameHeader(regT1, RegisterFile::ReturnPC); // Calling convention: f(edi, esi, edx, ecx, ...); // Host function signature: f(ExecState*); @@ -250,7 +250,7 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon subPtr(TrustedImm32(16 - sizeof(void*)), stackPointerRegister); // Align stack after call. - emitGetFromCallFrameHeaderPtr(JSStack::Callee, X86Registers::esi); + emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86Registers::esi); loadPtr(Address(X86Registers::esi, OBJECT_OFFSETOF(JSFunction, m_executable)), X86Registers::r9); move(regT0, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack. call(Address(X86Registers::r9, executableOffsetToFunction)); @@ -260,18 +260,18 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon #elif CPU(ARM) // Load caller frame's scope chain into this callframe so that whatever we call can // get to its global data. - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, regT2); - emitGetFromCallFrameHeaderPtr(JSStack::ScopeChain, regT1, regT2); - emitPutCellToCallFrameHeader(regT1, JSStack::ScopeChain); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2); + emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT2); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); preserveReturnAddressAfterCall(regT3); // Callee preserved - emitPutToCallFrameHeader(regT3, JSStack::ReturnPC); + emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC); // Calling convention: f(r0 == regT0, r1 == regT1, ...); // Host function signature: f(ExecState*); move(callFrameRegister, ARMRegisters::r0); - emitGetFromCallFrameHeaderPtr(JSStack::Callee, ARMRegisters::r1); + emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, ARMRegisters::r1); move(regT2, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack. loadPtr(Address(ARMRegisters::r1, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2); call(Address(regT2, executableOffsetToFunction)); @@ -281,12 +281,12 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon #elif CPU(MIPS) // Load caller frame's scope chain into this callframe so that whatever we call can // get to its global data. - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, regT0); - emitGetFromCallFrameHeaderPtr(JSStack::ScopeChain, regT1, regT0); - emitPutCellToCallFrameHeader(regT1, JSStack::ScopeChain); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT0); + emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT0); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); preserveReturnAddressAfterCall(regT3); // Callee preserved - emitPutToCallFrameHeader(regT3, JSStack::ReturnPC); + emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC); // Calling convention: f(a0, a1, a2, a3); // Host function signature: f(ExecState*); @@ -299,7 +299,7 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon move(callFrameRegister, MIPSRegisters::a0); // Call - emitGetFromCallFrameHeaderPtr(JSStack::Callee, MIPSRegisters::a2); + emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, MIPSRegisters::a2); loadPtr(Address(MIPSRegisters::a2, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2); move(regT0, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack. call(Address(regT2, executableOffsetToFunction)); @@ -382,7 +382,7 @@ void JIT::emit_op_end(Instruction* currentInstruction) { ASSERT(returnValueRegister != callFrameRegister); emitGetVirtualRegister(currentInstruction[1].u.operand, returnValueRegister); - restoreReturnAddressBeforeReturn(Address(callFrameRegister, JSStack::ReturnPC * static_cast<int>(sizeof(Register)))); + restoreReturnAddressBeforeReturn(Address(callFrameRegister, RegisterFile::ReturnPC * static_cast<int>(sizeof(Register)))); ret(); } @@ -583,10 +583,10 @@ void JIT::emit_op_ret(Instruction* currentInstruction) emitGetVirtualRegister(currentInstruction[1].u.operand, returnValueRegister); // Grab the return address. - emitGetFromCallFrameHeaderPtr(JSStack::ReturnPC, regT1); + emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1); // Restore our caller's "r". - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, callFrameRegister); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister); // Return. restoreReturnAddressBeforeReturn(regT1); @@ -606,10 +606,10 @@ void JIT::emit_op_ret_object_or_this(Instruction* currentInstruction) Jump notObject = emitJumpIfNotObject(regT2); // Grab the return address. - emitGetFromCallFrameHeaderPtr(JSStack::ReturnPC, regT1); + emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1); // Restore our caller's "r". - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, callFrameRegister); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister); // Return. restoreReturnAddressBeforeReturn(regT1); @@ -621,10 +621,10 @@ void JIT::emit_op_ret_object_or_this(Instruction* currentInstruction) emitGetVirtualRegister(currentInstruction[2].u.operand, returnValueRegister); // Grab the return address. - emitGetFromCallFrameHeaderPtr(JSStack::ReturnPC, regT1); + emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1); // Restore our caller's "r". - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, callFrameRegister); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister); // Return. restoreReturnAddressBeforeReturn(regT1); @@ -798,11 +798,11 @@ void JIT::emit_op_jneq_null(Instruction* currentInstruction) void JIT::emit_op_jneq_ptr(Instruction* currentInstruction) { unsigned src = currentInstruction[1].u.operand; - Special::Pointer ptr = currentInstruction[2].u.specialPointer; + JSCell* ptr = currentInstruction[2].u.jsCell.get(); unsigned target = currentInstruction[3].u.operand; emitGetVirtualRegister(src, regT0); - addJump(branchPtr(NotEqual, regT0, TrustedImmPtr(actualPointerFor(m_codeBlock, ptr))), target); + addJump(branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(JSValue(ptr)))), target); } void JIT::emit_op_eq(Instruction* currentInstruction) @@ -1285,7 +1285,7 @@ void JIT::emit_op_convert_this(Instruction* currentInstruction) void JIT::emit_op_create_this(Instruction* currentInstruction) { - emitGetFromCallFrameHeaderPtr(JSStack::Callee, regT0); + emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT0); loadPtr(Address(regT0, JSFunction::offsetOfCachedInheritorID()), regT2); addSlowCase(branchTestPtr(Zero, regT2)); @@ -1509,7 +1509,7 @@ void JIT::emit_op_get_arguments_length(Instruction* currentInstruction) int dst = currentInstruction[1].u.operand; int argumentsRegister = currentInstruction[2].u.operand; addSlowCase(branchTestPtr(NonZero, addressFor(argumentsRegister))); - emitGetFromCallFrameHeader32(JSStack::ArgumentCount, regT0); + emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0); sub32(TrustedImm32(1), regT0); emitFastArithReTagImmediate(regT0, regT0); emitPutVirtualRegister(dst, regT0); @@ -1539,7 +1539,7 @@ void JIT::emit_op_get_argument_by_val(Instruction* currentInstruction) addSlowCase(emitJumpIfNotImmediateInteger(regT1)); add32(TrustedImm32(1), regT1); // regT1 now contains the integer index of the argument we want, including this - emitGetFromCallFrameHeader32(JSStack::ArgumentCount, regT2); + emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT2); addSlowCase(branch32(AboveOrEqual, regT1, regT2)); neg32(regT1); @@ -1565,7 +1565,7 @@ void JIT::emitSlow_op_get_argument_by_val(Instruction* currentInstruction, Vecto emitPutVirtualRegister(unmodifiedArgumentsRegister(arguments)); skipArgumentsCreation.link(this); - JITStubCall stubCall(this, cti_op_get_by_val_generic); + JITStubCall stubCall(this, cti_op_get_by_val); stubCall.addArgument(arguments, regT2); stubCall.addArgument(property, regT2); stubCall.callWithValueProfiling(dst); @@ -1577,7 +1577,7 @@ void JIT::emit_op_resolve_global_dynamic(Instruction* currentInstruction) { int skip = currentInstruction[5].u.operand; - emitGetFromCallFrameHeaderPtr(JSStack::ScopeChain, regT0); + emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT0); bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain(); ASSERT(skip || !checkTopLevel); @@ -1661,8 +1661,7 @@ void JIT::emit_op_new_func_exp(Instruction* currentInstruction) void JIT::emit_op_new_array(Instruction* currentInstruction) { int length = currentInstruction[3].u.operand; - if (m_codeBlock->globalObject()->isHavingABadTime() - || CopiedSpace::isOversize(Butterfly::totalSize(0, 0, true, ArrayStorage::sizeFor(length)))) { + if (CopiedSpace::isOversize(Butterfly::totalSize(0, 0, true, ArrayStorage::sizeFor(length)))) { JITStubCall stubCall(this, cti_op_new_array); stubCall.addArgument(TrustedImm32(currentInstruction[2].u.operand)); stubCall.addArgument(TrustedImm32(currentInstruction[3].u.operand)); @@ -1681,10 +1680,8 @@ void JIT::emitSlow_op_new_array(Instruction* currentInstruction, Vector<SlowCase // If the allocation would be oversize, we will already make the proper stub call above in // emit_op_new_array. int length = currentInstruction[3].u.operand; - if (m_codeBlock->globalObject()->isHavingABadTime() - || CopiedSpace::isOversize(Butterfly::totalSize(0, 0, true, ArrayStorage::sizeFor(length)))) + if (CopiedSpace::isOversize(Butterfly::totalSize(0, 0, true, ArrayStorage::sizeFor(length)))) return; - linkSlowCase(iter); // We're having a bad time. linkSlowCase(iter); // Not enough space in CopiedSpace for storage. linkSlowCase(iter); // Not enough space in MarkedSpace for cell. diff --git a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp index db5365535..21744fba8 100644 --- a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp +++ b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp @@ -70,11 +70,11 @@ PassRefPtr<ExecutableMemoryHandle> JIT::privateCompileCTIMachineTrampolines(JSGl // Finish canonical initialization before JS function call. loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scope)), regT1); - emitPutCellToCallFrameHeader(regT1, JSStack::ScopeChain); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); // Also initialize ReturnPC for use by lazy linking and exceptions. preserveReturnAddressAfterCall(regT3); - emitPutToCallFrameHeader(regT3, JSStack::ReturnPC); + emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC); storePtr(callFrameRegister, &m_globalData->topCallFrame); restoreArgumentReference(); @@ -90,11 +90,11 @@ PassRefPtr<ExecutableMemoryHandle> JIT::privateCompileCTIMachineTrampolines(JSGl // Finish canonical initialization before JS function call. loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scope)), regT1); - emitPutCellToCallFrameHeader(regT1, JSStack::ScopeChain); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); // Also initialize ReturnPC for use by lazy linking and exeptions. preserveReturnAddressAfterCall(regT3); - emitPutToCallFrameHeader(regT3, JSStack::ReturnPC); + emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC); storePtr(callFrameRegister, &m_globalData->topCallFrame); restoreArgumentReference(); @@ -110,7 +110,7 @@ PassRefPtr<ExecutableMemoryHandle> JIT::privateCompileCTIMachineTrampolines(JSGl // Finish canonical initialization before JS function call. loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scope)), regT1); - emitPutCellToCallFrameHeader(regT1, JSStack::ScopeChain); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2); Jump hasCodeBlock1 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForCall)), TrustedImm32(0)); @@ -134,7 +134,7 @@ PassRefPtr<ExecutableMemoryHandle> JIT::privateCompileCTIMachineTrampolines(JSGl // Finish canonical initialization before JS function call. loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scope)), regT1); - emitPutCellToCallFrameHeader(regT1, JSStack::ScopeChain); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2); Jump hasCodeBlock2 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForConstruct)), TrustedImm32(0)); @@ -152,37 +152,37 @@ PassRefPtr<ExecutableMemoryHandle> JIT::privateCompileCTIMachineTrampolines(JSGl callSlowCase.link(this); // Finish canonical initialization before JS function call. - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, regT2); - emitGetFromCallFrameHeaderPtr(JSStack::ScopeChain, regT2, regT2); - emitPutCellToCallFrameHeader(regT2, JSStack::ScopeChain); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2); + emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2, regT2); + emitPutCellToCallFrameHeader(regT2, RegisterFile::ScopeChain); // Also initialize ReturnPC and CodeBlock, like a JS function would. preserveReturnAddressAfterCall(regT3); - emitPutToCallFrameHeader(regT3, JSStack::ReturnPC); - emitPutImmediateToCallFrameHeader(0, JSStack::CodeBlock); + emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC); + emitPutImmediateToCallFrameHeader(0, RegisterFile::CodeBlock); storePtr(callFrameRegister, &m_globalData->topCallFrame); restoreArgumentReference(); Call callCallNotJSFunction = call(); - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, callFrameRegister); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister); restoreReturnAddressBeforeReturn(regT3); ret(); constructSlowCase.link(this); // Finish canonical initialization before JS function call. - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, regT2); - emitGetFromCallFrameHeaderPtr(JSStack::ScopeChain, regT2, regT2); - emitPutCellToCallFrameHeader(regT2, JSStack::ScopeChain); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2); + emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2, regT2); + emitPutCellToCallFrameHeader(regT2, RegisterFile::ScopeChain); // Also initialize ReturnPC and CodeBlock, like a JS function would. preserveReturnAddressAfterCall(regT3); - emitPutToCallFrameHeader(regT3, JSStack::ReturnPC); - emitPutImmediateToCallFrameHeader(0, JSStack::CodeBlock); + emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC); + emitPutImmediateToCallFrameHeader(0, RegisterFile::CodeBlock); storePtr(callFrameRegister, &m_globalData->topCallFrame); restoreArgumentReference(); Call callConstructNotJSFunction = call(); - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, callFrameRegister); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister); restoreReturnAddressBeforeReturn(regT3); ret(); @@ -227,18 +227,18 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon Label nativeCallThunk = align(); - emitPutImmediateToCallFrameHeader(0, JSStack::CodeBlock); + emitPutImmediateToCallFrameHeader(0, RegisterFile::CodeBlock); storePtr(callFrameRegister, &m_globalData->topCallFrame); #if CPU(X86) // Load caller frame's scope chain into this callframe so that whatever we call can // get to its global data. - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, regT0); - emitGetFromCallFrameHeaderPtr(JSStack::ScopeChain, regT1, regT0); - emitPutCellToCallFrameHeader(regT1, JSStack::ScopeChain); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT0); + emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT0); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); peek(regT1); - emitPutToCallFrameHeader(regT1, JSStack::ReturnPC); + emitPutToCallFrameHeader(regT1, RegisterFile::ReturnPC); // Calling convention: f(ecx, edx, ...); // Host function signature: f(ExecState*); @@ -247,7 +247,7 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon subPtr(TrustedImm32(16 - sizeof(void*)), stackPointerRegister); // Align stack after call. // call the function - emitGetFromCallFrameHeaderPtr(JSStack::Callee, regT1); + emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT1); loadPtr(Address(regT1, OBJECT_OFFSETOF(JSFunction, m_executable)), regT1); move(regT0, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack. call(Address(regT1, executableOffsetToFunction)); @@ -257,19 +257,19 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon #elif CPU(ARM) // Load caller frame's scope chain into this callframe so that whatever we call can // get to its global data. - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, regT2); - emitGetFromCallFrameHeaderPtr(JSStack::ScopeChain, regT1, regT2); - emitPutCellToCallFrameHeader(regT1, JSStack::ScopeChain); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2); + emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT2); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); preserveReturnAddressAfterCall(regT3); // Callee preserved - emitPutToCallFrameHeader(regT3, JSStack::ReturnPC); + emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC); // Calling convention: f(r0 == regT0, r1 == regT1, ...); // Host function signature: f(ExecState*); move(callFrameRegister, ARMRegisters::r0); // call the function - emitGetFromCallFrameHeaderPtr(JSStack::Callee, ARMRegisters::r1); + emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, ARMRegisters::r1); move(regT2, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack. loadPtr(Address(ARMRegisters::r1, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2); call(Address(regT2, executableOffsetToFunction)); @@ -278,18 +278,18 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon #elif CPU(SH4) // Load caller frame's scope chain into this callframe so that whatever we call can // get to its global data. - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, regT2); - emitGetFromCallFrameHeaderPtr(JSStack::ScopeChain, regT1, regT2); - emitPutCellToCallFrameHeader(regT1, JSStack::ScopeChain); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2); + emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT2); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); preserveReturnAddressAfterCall(regT3); // Callee preserved - emitPutToCallFrameHeader(regT3, JSStack::ReturnPC); + emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC); // Calling convention: f(r0 == regT4, r1 == regT5, ...); // Host function signature: f(ExecState*); move(callFrameRegister, regT4); - emitGetFromCallFrameHeaderPtr(JSStack::Callee, regT5); + emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT5); move(regT2, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack. loadPtr(Address(regT5, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2); @@ -298,12 +298,12 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon #elif CPU(MIPS) // Load caller frame's scope chain into this callframe so that whatever we call can // get to its global data. - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, regT0); - emitGetFromCallFrameHeaderPtr(JSStack::ScopeChain, regT1, regT0); - emitPutCellToCallFrameHeader(regT1, JSStack::ScopeChain); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT0); + emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT0); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); preserveReturnAddressAfterCall(regT3); // Callee preserved - emitPutToCallFrameHeader(regT3, JSStack::ReturnPC); + emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC); // Calling convention: f(a0, a1, a2, a3); // Host function signature: f(ExecState*); @@ -316,7 +316,7 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon move(callFrameRegister, MIPSRegisters::a0); // Call - emitGetFromCallFrameHeaderPtr(JSStack::Callee, MIPSRegisters::a2); + emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, MIPSRegisters::a2); loadPtr(Address(MIPSRegisters::a2, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2); move(regT0, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack. call(Address(regT2, executableOffsetToFunction)); @@ -362,18 +362,18 @@ JIT::CodeRef JIT::privateCompileCTINativeCall(JSGlobalData* globalData, NativeFu { Call nativeCall; - emitPutImmediateToCallFrameHeader(0, JSStack::CodeBlock); + emitPutImmediateToCallFrameHeader(0, RegisterFile::CodeBlock); storePtr(callFrameRegister, &m_globalData->topCallFrame); #if CPU(X86) // Load caller frame's scope chain into this callframe so that whatever we call can // get to its global data. - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, regT0); - emitGetFromCallFrameHeaderPtr(JSStack::ScopeChain, regT1, regT0); - emitPutCellToCallFrameHeader(regT1, JSStack::ScopeChain); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT0); + emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT0); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); peek(regT1); - emitPutToCallFrameHeader(regT1, JSStack::ReturnPC); + emitPutToCallFrameHeader(regT1, RegisterFile::ReturnPC); // Calling convention: f(ecx, edx, ...); // Host function signature: f(ExecState*); @@ -391,18 +391,18 @@ JIT::CodeRef JIT::privateCompileCTINativeCall(JSGlobalData* globalData, NativeFu #elif CPU(ARM) // Load caller frame's scope chain into this callframe so that whatever we call can // get to its global data. - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, regT2); - emitGetFromCallFrameHeaderPtr(JSStack::ScopeChain, regT1, regT2); - emitPutCellToCallFrameHeader(regT1, JSStack::ScopeChain); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2); + emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT2); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); preserveReturnAddressAfterCall(regT3); // Callee preserved - emitPutToCallFrameHeader(regT3, JSStack::ReturnPC); + emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC); // Calling convention: f(r0 == regT0, r1 == regT1, ...); // Host function signature: f(ExecState*); move(callFrameRegister, ARMRegisters::r0); - emitGetFromCallFrameHeaderPtr(JSStack::Callee, ARMRegisters::r1); + emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, ARMRegisters::r1); move(regT2, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack. loadPtr(Address(ARMRegisters::r1, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2); @@ -414,12 +414,12 @@ JIT::CodeRef JIT::privateCompileCTINativeCall(JSGlobalData* globalData, NativeFu #elif CPU(MIPS) // Load caller frame's scope chain into this callframe so that whatever we call can // get to its global data. - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, regT0); - emitGetFromCallFrameHeaderPtr(JSStack::ScopeChain, regT1, regT0); - emitPutCellToCallFrameHeader(regT1, JSStack::ScopeChain); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT0); + emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT0); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); preserveReturnAddressAfterCall(regT3); // Callee preserved - emitPutToCallFrameHeader(regT3, JSStack::ReturnPC); + emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC); // Calling convention: f(a0, a1, a2, a3); // Host function signature: f(ExecState*); @@ -432,7 +432,7 @@ JIT::CodeRef JIT::privateCompileCTINativeCall(JSGlobalData* globalData, NativeFu move(callFrameRegister, MIPSRegisters::a0); // Call - emitGetFromCallFrameHeaderPtr(JSStack::Callee, MIPSRegisters::a2); + emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, MIPSRegisters::a2); loadPtr(Address(MIPSRegisters::a2, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2); move(regT0, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack. @@ -446,18 +446,18 @@ JIT::CodeRef JIT::privateCompileCTINativeCall(JSGlobalData* globalData, NativeFu #elif CPU(SH4) // Load caller frame's scope chain into this callframe so that whatever we call can // get to its global data. - emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, regT2); - emitGetFromCallFrameHeaderPtr(JSStack::ScopeChain, regT1, regT2); - emitPutCellToCallFrameHeader(regT1, JSStack::ScopeChain); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2); + emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT2); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); preserveReturnAddressAfterCall(regT3); // Callee preserved - emitPutToCallFrameHeader(regT3, JSStack::ReturnPC); + emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC); // Calling convention: f(r0 == regT4, r1 == regT5, ...); // Host function signature: f(ExecState*); move(callFrameRegister, regT4); - emitGetFromCallFrameHeaderPtr(JSStack::Callee, regT5); + emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT5); move(regT2, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack. loadPtr(Address(regT5, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2); @@ -518,7 +518,7 @@ void JIT::emit_op_end(Instruction* currentInstruction) { ASSERT(returnValueRegister != callFrameRegister); emitLoad(currentInstruction[1].u.operand, regT1, regT0); - restoreReturnAddressBeforeReturn(Address(callFrameRegister, JSStack::ReturnPC * static_cast<int>(sizeof(Register)))); + restoreReturnAddressBeforeReturn(Address(callFrameRegister, RegisterFile::ReturnPC * static_cast<int>(sizeof(Register)))); ret(); } @@ -975,12 +975,12 @@ void JIT::emit_op_jneq_null(Instruction* currentInstruction) void JIT::emit_op_jneq_ptr(Instruction* currentInstruction) { unsigned src = currentInstruction[1].u.operand; - Special::Pointer ptr = currentInstruction[2].u.specialPointer; + JSCell* ptr = currentInstruction[2].u.jsCell.get(); unsigned target = currentInstruction[3].u.operand; emitLoad(src, regT1, regT0); addJump(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)), target); - addJump(branchPtr(NotEqual, regT0, TrustedImmPtr(actualPointerFor(m_codeBlock, ptr))), target); + addJump(branchPtr(NotEqual, regT0, TrustedImmPtr(ptr)), target); } void JIT::emit_op_eq(Instruction* currentInstruction) @@ -1544,7 +1544,7 @@ void JIT::emit_op_init_lazy_reg(Instruction* currentInstruction) void JIT::emit_op_create_this(Instruction* currentInstruction) { - emitGetFromCallFrameHeaderPtr(JSStack::Callee, regT0); + emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT0); loadPtr(Address(regT0, JSFunction::offsetOfCachedInheritorID()), regT2); addSlowCase(branchTestPtr(Zero, regT2)); @@ -1626,7 +1626,7 @@ void JIT::emit_op_get_arguments_length(Instruction* currentInstruction) int dst = currentInstruction[1].u.operand; int argumentsRegister = currentInstruction[2].u.operand; addSlowCase(branch32(NotEqual, tagFor(argumentsRegister), TrustedImm32(JSValue::EmptyValueTag))); - load32(payloadFor(JSStack::ArgumentCount), regT0); + load32(payloadFor(RegisterFile::ArgumentCount), regT0); sub32(TrustedImm32(1), regT0); emitStoreInt32(dst, regT0); } @@ -1654,7 +1654,7 @@ void JIT::emit_op_get_argument_by_val(Instruction* currentInstruction) addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); add32(TrustedImm32(1), regT2); // regT2 now contains the integer index of the argument we want, including this - load32(payloadFor(JSStack::ArgumentCount), regT3); + load32(payloadFor(RegisterFile::ArgumentCount), regT3); addSlowCase(branch32(AboveOrEqual, regT2, regT3)); neg32(regT2); @@ -1680,7 +1680,7 @@ void JIT::emitSlow_op_get_argument_by_val(Instruction* currentInstruction, Vecto emitStore(unmodifiedArgumentsRegister(arguments), regT1, regT0); skipArgumentsCreation.link(this); - JITStubCall stubCall(this, cti_op_get_by_val_generic); + JITStubCall stubCall(this, cti_op_get_by_val); stubCall.addArgument(arguments); stubCall.addArgument(property); stubCall.callWithValueProfiling(dst); diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp index 9deded62a..b4d52e225 100644 --- a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp +++ b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp @@ -97,7 +97,6 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction) unsigned dst = currentInstruction[1].u.operand; unsigned base = currentInstruction[2].u.operand; unsigned property = currentInstruction[3].u.operand; - ArrayProfile* profile = currentInstruction[4].u.arrayProfile; emitGetVirtualRegisters(base, regT0, property, regT1); emitJumpSlowCaseIfNotImmediateInteger(regT1); @@ -112,69 +111,17 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction) emitJumpSlowCaseIfNotJSCell(regT0, base); loadPtr(Address(regT0, JSCell::structureOffset()), regT2); - emitArrayProfilingSite(regT2, regT3, profile); - and32(TrustedImm32(IndexingShapeMask), regT2); - - PatchableJump badType; - JumpList slowCases; - - JITArrayMode mode = chooseArrayMode(profile); - switch (mode) { - case JITContiguous: - slowCases = emitContiguousGetByVal(currentInstruction, badType); - break; - case JITArrayStorage: - slowCases = emitArrayStorageGetByVal(currentInstruction, badType); - break; - default: - CRASH(); - break; - } - - addSlowCase(badType); - addSlowCase(slowCases); - - Label done = label(); - -#if !ASSERT_DISABLED - Jump resultOK = branchTestPtr(NonZero, regT0); - breakpoint(); - resultOK.link(this); -#endif + emitArrayProfilingSite(regT2, regT3, currentInstruction[4].u.arrayProfile); + addSlowCase(branchTest32(Zero, regT2, TrustedImm32(HasArrayStorage))); - emitValueProfilingSite(); - emitPutVirtualRegister(dst); - - m_byValCompilationInfo.append(ByValCompilationInfo(m_bytecodeOffset, badType, mode, done)); -} - -JIT::JumpList JIT::emitContiguousGetByVal(Instruction*, PatchableJump& badType) -{ - JumpList slowCases; - - badType = patchableBranch32(NotEqual, regT2, TrustedImm32(ContiguousShape)); loadPtr(Address(regT0, JSObject::butterflyOffset()), regT2); - slowCases.append(branch32(AboveOrEqual, regT1, Address(regT2, Butterfly::offsetOfPublicLength()))); - loadPtr(BaseIndex(regT2, regT1, ScalePtr), regT0); - slowCases.append(branchTestPtr(Zero, regT0)); - - return slowCases; -} + addSlowCase(branch32(AboveOrEqual, regT1, Address(regT2, ArrayStorage::vectorLengthOffset()))); -JIT::JumpList JIT::emitArrayStorageGetByVal(Instruction*, PatchableJump& badType) -{ - JumpList slowCases; - - add32(TrustedImm32(-ArrayStorageShape), regT2, regT3); - badType = patchableBranch32(Above, regT3, TrustedImm32(SlowPutArrayStorageShape - ArrayStorageShape)); + loadPtr(BaseIndex(regT2, regT1, ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), regT0); + addSlowCase(branchTestPtr(Zero, regT0)); - loadPtr(Address(regT0, JSObject::butterflyOffset()), regT2); - slowCases.append(branch32(AboveOrEqual, regT1, Address(regT2, ArrayStorage::vectorLengthOffset()))); - - loadPtr(BaseIndex(regT2, regT1, ScalePtr, ArrayStorage::vectorOffset()), regT0); - slowCases.append(branchTestPtr(Zero, regT0)); - - return slowCases; + emitValueProfilingSite(); + emitPutVirtualRegister(dst); } void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) @@ -199,16 +146,10 @@ void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCas linkSlowCase(iter); // vector length check linkSlowCase(iter); // empty value - Label slowPath = label(); - JITStubCall stubCall(this, cti_op_get_by_val); stubCall.addArgument(base, regT2); stubCall.addArgument(property, regT2); - Call call = stubCall.call(dst); - - m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath; - m_byValCompilationInfo[m_byValInstructionIndex].returnAddress = call; - m_byValInstructionIndex++; + stubCall.call(dst); emitValueProfilingSite(); } @@ -218,16 +159,16 @@ void JIT::compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID ASSERT(sizeof(JSValue) == 8); if (finalObjectMode == MayBeFinal) { - Jump isInline = branch32(LessThan, offset, TrustedImm32(firstOutOfLineOffset)); + Jump isInline = branch32(LessThan, offset, TrustedImm32(inlineStorageCapacity)); loadPtr(Address(base, JSObject::butterflyOffset()), scratch); neg32(offset); Jump done = jump(); isInline.link(this); - addPtr(TrustedImm32(JSObject::offsetOfInlineStorage() - (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue)), base, scratch); + addPtr(TrustedImm32(JSObject::offsetOfInlineStorage() - (inlineStorageCapacity - 2) * sizeof(EncodedJSValue)), base, scratch); done.link(this); } else { #if !ASSERT_DISABLED - Jump isOutOfLine = branch32(GreaterThanOrEqual, offset, TrustedImm32(firstOutOfLineOffset)); + Jump isOutOfLine = branch32(GreaterThanOrEqual, offset, TrustedImm32(inlineStorageCapacity)); breakpoint(); isOutOfLine.link(this); #endif @@ -235,7 +176,7 @@ void JIT::compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID neg32(offset); } signExtend32ToPtr(offset, offset); - loadPtr(BaseIndex(scratch, offset, ScalePtr, (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue)), result); + loadPtr(BaseIndex(scratch, offset, ScalePtr, (inlineStorageCapacity - 2) * static_cast<ptrdiff_t>(sizeof(JSValue))), result); } void JIT::emit_op_get_by_pname(Instruction* currentInstruction) @@ -258,10 +199,7 @@ void JIT::emit_op_get_by_pname(Instruction* currentInstruction) load32(addressFor(i), regT3); sub32(TrustedImm32(1), regT3); addSlowCase(branch32(AboveOrEqual, regT3, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_numCacheableSlots)))); - Jump inlineProperty = branch32(Below, regT3, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructureInlineCapacity))); - add32(TrustedImm32(firstOutOfLineOffset), regT3); - sub32(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructureInlineCapacity)), regT3); - inlineProperty.link(this); + add32(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_offsetBase)), regT3); compileGetDirectOffset(regT0, regT0, regT3, regT1); emitPutVirtualRegister(dst, regT0); @@ -288,7 +226,7 @@ void JIT::emit_op_put_by_val(Instruction* currentInstruction) { unsigned base = currentInstruction[1].u.operand; unsigned property = currentInstruction[2].u.operand; - ArrayProfile* profile = currentInstruction[4].u.arrayProfile; + unsigned value = currentInstruction[3].u.operand; emitGetVirtualRegisters(base, regT0, property, regT1); emitJumpSlowCaseIfNotImmediateInteger(regT1); @@ -296,76 +234,10 @@ void JIT::emit_op_put_by_val(Instruction* currentInstruction) zeroExtend32ToPtr(regT1, regT1); emitJumpSlowCaseIfNotJSCell(regT0, base); loadPtr(Address(regT0, JSCell::structureOffset()), regT2); - emitArrayProfilingSite(regT2, regT3, profile); - and32(TrustedImm32(IndexingShapeMask), regT2); - - PatchableJump badType; - JumpList slowCases; - - JITArrayMode mode = chooseArrayMode(profile); - switch (mode) { - case JITContiguous: - slowCases = emitContiguousPutByVal(currentInstruction, badType); - break; - case JITArrayStorage: - slowCases = emitArrayStoragePutByVal(currentInstruction, badType); - break; - default: - CRASH(); - break; - } - - addSlowCase(badType); - addSlowCase(slowCases); - - Label done = label(); - - m_byValCompilationInfo.append(ByValCompilationInfo(m_bytecodeOffset, badType, mode, done)); - - emitWriteBarrier(regT0, regT3, regT1, regT3, ShouldFilterImmediates, WriteBarrierForPropertyAccess); -} - -JIT::JumpList JIT::emitContiguousPutByVal(Instruction* currentInstruction, PatchableJump& badType) -{ - unsigned value = currentInstruction[3].u.operand; - ArrayProfile* profile = currentInstruction[4].u.arrayProfile; - - badType = patchableBranch32(NotEqual, regT2, TrustedImm32(ContiguousShape)); - + emitArrayProfilingSite(regT2, regT3, currentInstruction[4].u.arrayProfile); + addSlowCase(branchTest32(Zero, regT2, TrustedImm32(HasArrayStorage))); loadPtr(Address(regT0, JSObject::butterflyOffset()), regT2); - Jump outOfBounds = branch32(AboveOrEqual, regT1, Address(regT2, Butterfly::offsetOfPublicLength())); - - Label storeResult = label(); - emitGetVirtualRegister(value, regT3); - storePtr(regT3, BaseIndex(regT2, regT1, ScalePtr)); - - Jump done = jump(); - outOfBounds.link(this); - - JumpList slowCases; - slowCases.append(branch32(AboveOrEqual, regT1, Address(regT2, Butterfly::offsetOfVectorLength()))); - - emitArrayProfileStoreToHoleSpecialCase(profile); - - add32(TrustedImm32(1), regT1, regT3); - store32(regT3, Address(regT2, Butterfly::offsetOfPublicLength())); - jump().linkTo(storeResult, this); - - done.link(this); - - return slowCases; -} - -JIT::JumpList JIT::emitArrayStoragePutByVal(Instruction* currentInstruction, PatchableJump& badType) -{ - unsigned value = currentInstruction[3].u.operand; - ArrayProfile* profile = currentInstruction[4].u.arrayProfile; - - JumpList slowCases; - - badType = patchableBranch32(NotEqual, regT2, TrustedImm32(ArrayStorageShape)); - loadPtr(Address(regT0, JSObject::butterflyOffset()), regT2); - slowCases.append(branch32(AboveOrEqual, regT1, Address(regT2, ArrayStorage::vectorLengthOffset()))); + addSlowCase(branch32(AboveOrEqual, regT1, Address(regT2, ArrayStorage::vectorLengthOffset()))); Jump empty = branchTestPtr(Zero, BaseIndex(regT2, regT1, ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))); @@ -375,8 +247,8 @@ JIT::JumpList JIT::emitArrayStoragePutByVal(Instruction* currentInstruction, Pat Jump end = jump(); empty.link(this); - emitArrayProfileStoreToHoleSpecialCase(profile); - add32(TrustedImm32(1), Address(regT2, ArrayStorage::numValuesInVectorOffset())); + emitArrayProfileStoreToHoleSpecialCase(currentInstruction[4].u.arrayProfile); + add32(TrustedImm32(1), Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); branch32(Below, regT1, Address(regT2, ArrayStorage::lengthOffset())).linkTo(storeResult, this); add32(TrustedImm32(1), regT1); @@ -385,8 +257,8 @@ JIT::JumpList JIT::emitArrayStoragePutByVal(Instruction* currentInstruction, Pat jump().linkTo(storeResult, this); end.link(this); - - return slowCases; + + emitWriteBarrier(regT0, regT3, regT1, regT3, ShouldFilterImmediates, WriteBarrierForPropertyAccess); } void JIT::emitSlow_op_put_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) @@ -398,19 +270,13 @@ void JIT::emitSlow_op_put_by_val(Instruction* currentInstruction, Vector<SlowCas linkSlowCase(iter); // property int32 check linkSlowCaseIfNotJSCell(iter, base); // base cell check linkSlowCase(iter); // base not array check - linkSlowCase(iter); // out of bounds - - Label slowPath = label(); + linkSlowCase(iter); // in vector check JITStubCall stubPutByValCall(this, cti_op_put_by_val); stubPutByValCall.addArgument(regT0); stubPutByValCall.addArgument(property, regT2); stubPutByValCall.addArgument(value, regT2); - Call call = stubPutByValCall.call(); - - m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath; - m_byValCompilationInfo[m_byValInstructionIndex].returnAddress = call; - m_byValInstructionIndex++; + stubPutByValCall.call(); } void JIT::emit_op_put_by_index(Instruction* currentInstruction) @@ -790,7 +656,7 @@ void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress) loadPtr(Address(regT0, JSCell::structureOffset()), regT2); emitArrayProfilingSiteForBytecodeIndex(regT2, regT1, stubInfo->bytecodeIndex); Jump failureCases1 = branchTest32(Zero, regT2, TrustedImm32(IsArray)); - Jump failureCases2 = branchTest32(Zero, regT2, TrustedImm32(IndexingShapeMask)); + Jump failureCases2 = branchTest32(Zero, regT2, TrustedImm32(HasArrayStorage)); // Checks out okay! - get the length from the storage loadPtr(Address(regT0, JSObject::butterflyOffset()), regT3); @@ -1194,7 +1060,7 @@ void JIT::emit_op_get_scoped_var(Instruction* currentInstruction) { int skip = currentInstruction[3].u.operand; - emitGetFromCallFrameHeaderPtr(JSStack::ScopeChain, regT0); + emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT0); bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain(); ASSERT(skip || !checkTopLevel); if (checkTopLevel && skip--) { @@ -1219,7 +1085,7 @@ void JIT::emit_op_put_scoped_var(Instruction* currentInstruction) emitGetVirtualRegister(currentInstruction[3].u.operand, regT0); - emitGetFromCallFrameHeaderPtr(JSStack::ScopeChain, regT1); + emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1); bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain(); ASSERT(skip || !checkTopLevel); if (checkTopLevel && skip--) { @@ -1408,377 +1274,6 @@ bool JIT::isDirectPutById(StructureStubInfo* stubInfo) } } -void JIT::privateCompileGetByVal(ByValInfo* byValInfo, ReturnAddressPtr returnAddress, JITArrayMode arrayMode) -{ - Instruction* currentInstruction = m_codeBlock->instructions().begin() + byValInfo->bytecodeIndex; - - PatchableJump badType; - JumpList slowCases; - - switch (arrayMode) { - case JITContiguous: - slowCases = emitContiguousGetByVal(currentInstruction, badType); - break; - case JITArrayStorage: - slowCases = emitArrayStorageGetByVal(currentInstruction, badType); - break; - case JITInt8Array: - slowCases = emitIntTypedArrayGetByVal(currentInstruction, badType, m_globalData->int8ArrayDescriptor(), 1, SignedTypedArray); - break; - case JITInt16Array: - slowCases = emitIntTypedArrayGetByVal(currentInstruction, badType, m_globalData->int16ArrayDescriptor(), 2, SignedTypedArray); - break; - case JITInt32Array: - slowCases = emitIntTypedArrayGetByVal(currentInstruction, badType, m_globalData->int32ArrayDescriptor(), 4, SignedTypedArray); - break; - case JITUint8Array: - case JITUint8ClampedArray: - slowCases = emitIntTypedArrayGetByVal(currentInstruction, badType, m_globalData->uint8ArrayDescriptor(), 1, UnsignedTypedArray); - break; - case JITUint16Array: - slowCases = emitIntTypedArrayGetByVal(currentInstruction, badType, m_globalData->uint16ArrayDescriptor(), 2, UnsignedTypedArray); - break; - case JITUint32Array: - slowCases = emitIntTypedArrayGetByVal(currentInstruction, badType, m_globalData->uint32ArrayDescriptor(), 4, UnsignedTypedArray); - break; - case JITFloat32Array: - slowCases = emitFloatTypedArrayGetByVal(currentInstruction, badType, m_globalData->float32ArrayDescriptor(), 4); - break; - case JITFloat64Array: - slowCases = emitFloatTypedArrayGetByVal(currentInstruction, badType, m_globalData->float64ArrayDescriptor(), 8); - break; - default: - CRASH(); - } - - Jump done = jump(); - - LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock); - - patchBuffer.link(badType, CodeLocationLabel(returnAddress.value()).labelAtOffset(byValInfo->returnAddressToSlowPath)); - patchBuffer.link(slowCases, CodeLocationLabel(returnAddress.value()).labelAtOffset(byValInfo->returnAddressToSlowPath)); - - patchBuffer.link(done, byValInfo->badTypeJump.labelAtOffset(byValInfo->badTypeJumpToDone)); - - byValInfo->stubRoutine = FINALIZE_CODE_FOR_STUB( - patchBuffer, - ("Baseline get_by_val stub for CodeBlock %p, return point %p", m_codeBlock, returnAddress.value())); - - RepatchBuffer repatchBuffer(m_codeBlock); - repatchBuffer.relink(byValInfo->badTypeJump, CodeLocationLabel(byValInfo->stubRoutine->code().code())); - repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_val_generic)); -} - -void JIT::privateCompilePutByVal(ByValInfo* byValInfo, ReturnAddressPtr returnAddress, JITArrayMode arrayMode) -{ - Instruction* currentInstruction = m_codeBlock->instructions().begin() + byValInfo->bytecodeIndex; - - PatchableJump badType; - JumpList slowCases; - - switch (arrayMode) { - case JITContiguous: - slowCases = emitContiguousPutByVal(currentInstruction, badType); - break; - case JITArrayStorage: - slowCases = emitArrayStoragePutByVal(currentInstruction, badType); - break; - case JITInt8Array: - slowCases = emitIntTypedArrayPutByVal(currentInstruction, badType, m_globalData->int8ArrayDescriptor(), 1, SignedTypedArray, TruncateRounding); - break; - case JITInt16Array: - slowCases = emitIntTypedArrayPutByVal(currentInstruction, badType, m_globalData->int16ArrayDescriptor(), 2, SignedTypedArray, TruncateRounding); - break; - case JITInt32Array: - slowCases = emitIntTypedArrayPutByVal(currentInstruction, badType, m_globalData->int32ArrayDescriptor(), 4, SignedTypedArray, TruncateRounding); - break; - case JITUint8Array: - slowCases = emitIntTypedArrayPutByVal(currentInstruction, badType, m_globalData->uint8ArrayDescriptor(), 1, UnsignedTypedArray, TruncateRounding); - break; - case JITUint8ClampedArray: - slowCases = emitIntTypedArrayPutByVal(currentInstruction, badType, m_globalData->uint8ClampedArrayDescriptor(), 1, UnsignedTypedArray, ClampRounding); - break; - case JITUint16Array: - slowCases = emitIntTypedArrayPutByVal(currentInstruction, badType, m_globalData->uint16ArrayDescriptor(), 2, UnsignedTypedArray, TruncateRounding); - break; - case JITUint32Array: - slowCases = emitIntTypedArrayPutByVal(currentInstruction, badType, m_globalData->uint32ArrayDescriptor(), 4, UnsignedTypedArray, TruncateRounding); - break; - case JITFloat32Array: - slowCases = emitFloatTypedArrayPutByVal(currentInstruction, badType, m_globalData->float32ArrayDescriptor(), 4); - break; - case JITFloat64Array: - slowCases = emitFloatTypedArrayPutByVal(currentInstruction, badType, m_globalData->float64ArrayDescriptor(), 8); - break; - default: - CRASH(); - break; - } - - Jump done = jump(); - - LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock); - - patchBuffer.link(badType, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(returnAddress.value())).labelAtOffset(byValInfo->returnAddressToSlowPath)); - patchBuffer.link(slowCases, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(returnAddress.value())).labelAtOffset(byValInfo->returnAddressToSlowPath)); - - patchBuffer.link(done, byValInfo->badTypeJump.labelAtOffset(byValInfo->badTypeJumpToDone)); - - byValInfo->stubRoutine = FINALIZE_CODE_FOR_STUB( - patchBuffer, - ("Baseline put_by_val stub for CodeBlock %p, return point %p", m_codeBlock, returnAddress.value())); - - RepatchBuffer repatchBuffer(m_codeBlock); - repatchBuffer.relink(byValInfo->badTypeJump, CodeLocationLabel(byValInfo->stubRoutine->code().code())); - repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_put_by_val_generic)); -} - -JIT::JumpList JIT::emitIntTypedArrayGetByVal(Instruction*, PatchableJump& badType, const TypedArrayDescriptor& descriptor, size_t elementSize, TypedArraySignedness signedness) -{ - // The best way to test the array type is to use the classInfo. We need to do so without - // clobbering the register that holds the indexing type, base, and property. - -#if USE(JSVALUE64) - RegisterID base = regT0; - RegisterID property = regT1; - RegisterID resultPayload = regT0; - RegisterID scratch = regT3; -#else - RegisterID base = regT0; - RegisterID property = regT2; - RegisterID resultPayload = regT0; - RegisterID resultTag = regT1; - RegisterID scratch = regT3; -#endif - - JumpList slowCases; - - loadPtr(Address(base, JSCell::structureOffset()), scratch); - badType = patchableBranchPtr(NotEqual, Address(scratch, Structure::classInfoOffset()), TrustedImmPtr(descriptor.m_classInfo)); - slowCases.append(branch32(AboveOrEqual, property, Address(base, descriptor.m_lengthOffset))); - loadPtr(Address(base, descriptor.m_storageOffset), base); - - switch (elementSize) { - case 1: - if (signedness == SignedTypedArray) - load8Signed(BaseIndex(base, property, TimesOne), resultPayload); - else - load8(BaseIndex(base, property, TimesOne), resultPayload); - break; - case 2: - if (signedness == SignedTypedArray) - load16Signed(BaseIndex(base, property, TimesTwo), resultPayload); - else - load16(BaseIndex(base, property, TimesTwo), resultPayload); - break; - case 4: - load32(BaseIndex(base, property, TimesFour), resultPayload); - break; - default: - CRASH(); - } - - Jump done; - if (elementSize == 4 && signedness == UnsignedTypedArray) { - Jump canBeInt = branch32(GreaterThanOrEqual, resultPayload, TrustedImm32(0)); - - convertInt32ToDouble(resultPayload, fpRegT0); - addDouble(AbsoluteAddress(&twoToThe32), fpRegT0); -#if USE(JSVALUE64) - moveDoubleToPtr(fpRegT0, resultPayload); - subPtr(tagTypeNumberRegister, resultPayload); -#else - moveDoubleToInts(fpRegT0, resultPayload, resultTag); -#endif - - done = jump(); - canBeInt.link(this); - } - -#if USE(JSVALUE64) - orPtr(tagTypeNumberRegister, resultPayload); -#else - move(TrustedImm32(JSValue::Int32Tag), resultTag); -#endif - if (done.isSet()) - done.link(this); - return slowCases; -} - -JIT::JumpList JIT::emitFloatTypedArrayGetByVal(Instruction*, PatchableJump& badType, const TypedArrayDescriptor& descriptor, size_t elementSize) -{ -#if USE(JSVALUE64) - RegisterID base = regT0; - RegisterID property = regT1; - RegisterID resultPayload = regT0; - RegisterID scratch = regT3; -#else - RegisterID base = regT0; - RegisterID property = regT2; - RegisterID resultPayload = regT0; - RegisterID resultTag = regT1; - RegisterID scratch = regT3; -#endif - - JumpList slowCases; - - loadPtr(Address(base, JSCell::structureOffset()), scratch); - badType = patchableBranchPtr(NotEqual, Address(scratch, Structure::classInfoOffset()), TrustedImmPtr(descriptor.m_classInfo)); - slowCases.append(branch32(AboveOrEqual, property, Address(base, descriptor.m_lengthOffset))); - loadPtr(Address(base, descriptor.m_storageOffset), base); - - switch (elementSize) { - case 4: - loadFloat(BaseIndex(base, property, TimesFour), fpRegT0); - convertFloatToDouble(fpRegT0, fpRegT0); - break; - case 8: { - loadDouble(BaseIndex(base, property, TimesEight), fpRegT0); - Jump notNaN = branchDouble(DoubleEqual, fpRegT0, fpRegT0); - static const double NaN = std::numeric_limits<double>::quiet_NaN(); - loadDouble(&NaN, fpRegT0); - notNaN.link(this); - break; - } - default: - CRASH(); - } - -#if USE(JSVALUE64) - moveDoubleToPtr(fpRegT0, resultPayload); - subPtr(tagTypeNumberRegister, resultPayload); -#else - moveDoubleToInts(fpRegT0, resultPayload, resultTag); -#endif - return slowCases; -} - -JIT::JumpList JIT::emitIntTypedArrayPutByVal(Instruction* currentInstruction, PatchableJump& badType, const TypedArrayDescriptor& descriptor, size_t elementSize, TypedArraySignedness signedness, TypedArrayRounding rounding) -{ - unsigned value = currentInstruction[3].u.operand; - -#if USE(JSVALUE64) - RegisterID base = regT0; - RegisterID property = regT1; - RegisterID earlyScratch = regT3; - RegisterID lateScratch = regT2; -#else - RegisterID base = regT0; - RegisterID property = regT2; - RegisterID earlyScratch = regT3; - RegisterID lateScratch = regT1; -#endif - - JumpList slowCases; - - loadPtr(Address(base, JSCell::structureOffset()), earlyScratch); - badType = patchableBranchPtr(NotEqual, Address(earlyScratch, Structure::classInfoOffset()), TrustedImmPtr(descriptor.m_classInfo)); - slowCases.append(branch32(AboveOrEqual, property, Address(base, descriptor.m_lengthOffset))); - -#if USE(JSVALUE64) - emitGetVirtualRegister(value, earlyScratch); - slowCases.append(emitJumpIfNotImmediateInteger(earlyScratch)); -#else - emitLoad(value, lateScratch, earlyScratch); - slowCases.append(branch32(NotEqual, lateScratch, TrustedImm32(JSValue::Int32Tag))); -#endif - - // We would be loading this into base as in get_by_val, except that the slow - // path expects the base to be unclobbered. - loadPtr(Address(base, descriptor.m_storageOffset), lateScratch); - - if (rounding == ClampRounding) { - ASSERT(elementSize == 1); - ASSERT_UNUSED(signedness, signedness = UnsignedTypedArray); - Jump inBounds = branch32(BelowOrEqual, earlyScratch, TrustedImm32(0xff)); - Jump tooBig = branch32(GreaterThan, earlyScratch, TrustedImm32(0xff)); - xor32(earlyScratch, earlyScratch); - Jump clamped = jump(); - tooBig.link(this); - move(TrustedImm32(0xff), earlyScratch); - clamped.link(this); - inBounds.link(this); - } - - switch (elementSize) { - case 1: - store8(earlyScratch, BaseIndex(lateScratch, property, TimesOne)); - break; - case 2: - store16(earlyScratch, BaseIndex(lateScratch, property, TimesTwo)); - break; - case 4: - store32(earlyScratch, BaseIndex(lateScratch, property, TimesFour)); - break; - default: - CRASH(); - } - - return slowCases; -} - -JIT::JumpList JIT::emitFloatTypedArrayPutByVal(Instruction* currentInstruction, PatchableJump& badType, const TypedArrayDescriptor& descriptor, size_t elementSize) -{ - unsigned value = currentInstruction[3].u.operand; - -#if USE(JSVALUE64) - RegisterID base = regT0; - RegisterID property = regT1; - RegisterID earlyScratch = regT3; - RegisterID lateScratch = regT2; -#else - RegisterID base = regT0; - RegisterID property = regT2; - RegisterID earlyScratch = regT3; - RegisterID lateScratch = regT1; -#endif - - JumpList slowCases; - - loadPtr(Address(base, JSCell::structureOffset()), earlyScratch); - badType = patchableBranchPtr(NotEqual, Address(earlyScratch, Structure::classInfoOffset()), TrustedImmPtr(descriptor.m_classInfo)); - slowCases.append(branch32(AboveOrEqual, property, Address(base, descriptor.m_lengthOffset))); - -#if USE(JSVALUE64) - emitGetVirtualRegister(value, earlyScratch); - Jump doubleCase = emitJumpIfNotImmediateInteger(earlyScratch); - convertInt32ToDouble(earlyScratch, fpRegT0); - Jump ready = jump(); - doubleCase.link(this); - slowCases.append(emitJumpIfNotImmediateNumber(earlyScratch)); - addPtr(tagTypeNumberRegister, earlyScratch); - movePtrToDouble(earlyScratch, fpRegT0); - ready.link(this); -#else - emitLoad(value, lateScratch, earlyScratch); - Jump doubleCase = branch32(NotEqual, lateScratch, TrustedImm32(JSValue::Int32Tag)); - convertInt32ToDouble(earlyScratch, fpRegT0); - Jump ready = jump(); - doubleCase.link(this); - slowCases.append(branch32(Above, lateScratch, TrustedImm32(JSValue::LowestTag))); - moveIntsToDouble(earlyScratch, lateScratch, fpRegT0, fpRegT1); - ready.link(this); -#endif - - // We would be loading this into base as in get_by_val, except that the slow - // path expects the base to be unclobbered. - loadPtr(Address(base, descriptor.m_storageOffset), lateScratch); - - switch (elementSize) { - case 4: - convertDoubleToFloat(fpRegT0, fpRegT0); - storeFloat(fpRegT0, BaseIndex(lateScratch, property, TimesFour)); - break; - case 8: - storeDouble(fpRegT0, BaseIndex(lateScratch, property, TimesEight)); - break; - default: - CRASH(); - } - - return slowCases; -} - } // namespace JSC #endif // ENABLE(JIT) diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp index e7c4a479b..ed561a28b 100644 --- a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp +++ b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp @@ -204,82 +204,27 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction) unsigned dst = currentInstruction[1].u.operand; unsigned base = currentInstruction[2].u.operand; unsigned property = currentInstruction[3].u.operand; - ArrayProfile* profile = currentInstruction[4].u.arrayProfile; emitLoad2(base, regT1, regT0, property, regT3, regT2); addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); emitJumpSlowCaseIfNotJSCell(base, regT1); loadPtr(Address(regT0, JSCell::structureOffset()), regT1); - emitArrayProfilingSite(regT1, regT3, profile); - and32(TrustedImm32(IndexingShapeMask), regT1); - - PatchableJump badType; - JumpList slowCases; - - JITArrayMode mode = chooseArrayMode(profile); - switch (mode) { - case JITContiguous: - slowCases = emitContiguousGetByVal(currentInstruction, badType); - break; - case JITArrayStorage: - slowCases = emitArrayStorageGetByVal(currentInstruction, badType); - break; - default: - CRASH(); - } - - addSlowCase(badType); - addSlowCase(slowCases); - - Label done = label(); - -#if !ASSERT_DISABLED - Jump resultOK = branch32(NotEqual, regT1, TrustedImm32(JSValue::EmptyValueTag)); - breakpoint(); - resultOK.link(this); -#endif - - emitValueProfilingSite(); - emitStore(dst, regT1, regT0); - map(m_bytecodeOffset + OPCODE_LENGTH(op_get_by_val), dst, regT1, regT0); - - m_byValCompilationInfo.append(ByValCompilationInfo(m_bytecodeOffset, badType, mode, done)); -} - -JIT::JumpList JIT::emitContiguousGetByVal(Instruction*, PatchableJump& badType) -{ - JumpList slowCases; - - badType = patchableBranch32(NotEqual, regT1, TrustedImm32(ContiguousShape)); - - loadPtr(Address(regT0, JSObject::butterflyOffset()), regT3); - slowCases.append(branch32(AboveOrEqual, regT2, Address(regT3, Butterfly::offsetOfPublicLength()))); - - load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1); // tag - load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0); // payload - slowCases.append(branch32(Equal, regT1, TrustedImm32(JSValue::EmptyValueTag))); - - return slowCases; -} - -JIT::JumpList JIT::emitArrayStorageGetByVal(Instruction*, PatchableJump& badType) -{ - JumpList slowCases; - - add32(TrustedImm32(-ArrayStorageShape), regT1, regT3); - badType = patchableBranch32(Above, regT3, TrustedImm32(SlowPutArrayStorageShape - ArrayStorageShape)); + emitArrayProfilingSite(regT1, regT3, currentInstruction[4].u.arrayProfile); + addSlowCase(branchTest32(Zero, regT1, TrustedImm32(HasArrayStorage))); loadPtr(Address(regT0, JSObject::butterflyOffset()), regT3); - slowCases.append(branch32(AboveOrEqual, regT2, Address(regT3, ArrayStorage::vectorLengthOffset()))); + addSlowCase(branch32(AboveOrEqual, regT2, Address(regT3, ArrayStorage::vectorLengthOffset()))); load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1); // tag load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0); // payload - slowCases.append(branch32(Equal, regT1, TrustedImm32(JSValue::EmptyValueTag))); + addSlowCase(branch32(Equal, regT1, TrustedImm32(JSValue::EmptyValueTag))); - return slowCases; + emitValueProfilingSite(); + emitStore(dst, regT1, regT0); + map(m_bytecodeOffset + OPCODE_LENGTH(op_get_by_val), dst, regT1, regT0); } - + void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) { unsigned dst = currentInstruction[1].u.operand; @@ -303,16 +248,10 @@ void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCas linkSlowCase(iter); // vector length check linkSlowCase(iter); // empty value - Label slowPath = label(); - JITStubCall stubCall(this, cti_op_get_by_val); stubCall.addArgument(base); stubCall.addArgument(property); - Call call = stubCall.call(dst); - - m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath; - m_byValCompilationInfo[m_byValInstructionIndex].returnAddress = call; - m_byValInstructionIndex++; + stubCall.call(dst); emitValueProfilingSite(); } @@ -321,86 +260,20 @@ void JIT::emit_op_put_by_val(Instruction* currentInstruction) { unsigned base = currentInstruction[1].u.operand; unsigned property = currentInstruction[2].u.operand; - ArrayProfile* profile = currentInstruction[4].u.arrayProfile; + unsigned value = currentInstruction[3].u.operand; emitLoad2(base, regT1, regT0, property, regT3, regT2); addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); emitJumpSlowCaseIfNotJSCell(base, regT1); loadPtr(Address(regT0, JSCell::structureOffset()), regT1); - emitArrayProfilingSite(regT1, regT3, profile); - and32(TrustedImm32(IndexingShapeMask), regT1); - - PatchableJump badType; - JumpList slowCases; - - JITArrayMode mode = chooseArrayMode(profile); - switch (mode) { - case JITContiguous: - slowCases = emitContiguousPutByVal(currentInstruction, badType); - break; - case JITArrayStorage: - slowCases = emitArrayStoragePutByVal(currentInstruction, badType); - break; - default: - CRASH(); - break; - } - - addSlowCase(badType); - addSlowCase(slowCases); - - Label done = label(); - - m_byValCompilationInfo.append(ByValCompilationInfo(m_bytecodeOffset, badType, mode, done)); -} - -JIT::JumpList JIT::emitContiguousPutByVal(Instruction* currentInstruction, PatchableJump& badType) -{ - unsigned value = currentInstruction[3].u.operand; - ArrayProfile* profile = currentInstruction[4].u.arrayProfile; - - JumpList slowCases; - - badType = patchableBranch32(NotEqual, regT1, TrustedImm32(ContiguousShape)); - + emitArrayProfilingSite(regT1, regT3, currentInstruction[4].u.arrayProfile); + addSlowCase(branchTest32(Zero, regT1, TrustedImm32(HasArrayStorage))); loadPtr(Address(regT0, JSObject::butterflyOffset()), regT3); - Jump outOfBounds = branch32(AboveOrEqual, regT2, Address(regT3, Butterfly::offsetOfPublicLength())); - - Label storeResult = label(); - emitLoad(value, regT1, regT0); - store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload))); - store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag))); - Jump done = jump(); - - outOfBounds.link(this); - slowCases.append(branch32(AboveOrEqual, regT2, Address(regT3, Butterfly::offsetOfVectorLength()))); - - emitArrayProfileStoreToHoleSpecialCase(profile); - - add32(TrustedImm32(1), regT2, regT1); - store32(regT1, Address(regT3, Butterfly::offsetOfPublicLength())); - jump().linkTo(storeResult, this); - - done.link(this); - - emitWriteBarrier(regT0, regT1, regT1, regT3, UnconditionalWriteBarrier, WriteBarrierForPropertyAccess); - - return slowCases; -} + addSlowCase(branch32(AboveOrEqual, regT2, Address(regT3, ArrayStorage::vectorLengthOffset()))); -JIT::JumpList JIT::emitArrayStoragePutByVal(Instruction* currentInstruction, PatchableJump& badType) -{ - unsigned value = currentInstruction[3].u.operand; - ArrayProfile* profile = currentInstruction[4].u.arrayProfile; - - JumpList slowCases; - - badType = patchableBranch32(NotEqual, regT1, TrustedImm32(ArrayStorageShape)); + emitWriteBarrier(regT0, regT1, regT1, regT3, UnconditionalWriteBarrier, WriteBarrierForPropertyAccess); - loadPtr(Address(regT0, JSObject::butterflyOffset()), regT3); - slowCases.append(branch32(AboveOrEqual, regT2, Address(regT3, ArrayStorage::vectorLengthOffset()))); - Jump empty = branch32(Equal, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag)); Label storeResult(this); @@ -410,7 +283,7 @@ JIT::JumpList JIT::emitArrayStoragePutByVal(Instruction* currentInstruction, Pat Jump end = jump(); empty.link(this); - emitArrayProfileStoreToHoleSpecialCase(profile); + emitArrayProfileStoreToHoleSpecialCase(currentInstruction[4].u.arrayProfile); add32(TrustedImm32(1), Address(regT3, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); branch32(Below, regT2, Address(regT3, ArrayStorage::lengthOffset())).linkTo(storeResult, this); @@ -419,10 +292,6 @@ JIT::JumpList JIT::emitArrayStoragePutByVal(Instruction* currentInstruction, Pat jump().linkTo(storeResult, this); end.link(this); - - emitWriteBarrier(regT0, regT1, regT1, regT3, UnconditionalWriteBarrier, WriteBarrierForPropertyAccess); - - return slowCases; } void JIT::emitSlow_op_put_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) @@ -434,19 +303,13 @@ void JIT::emitSlow_op_put_by_val(Instruction* currentInstruction, Vector<SlowCas linkSlowCase(iter); // property int32 check linkSlowCaseIfNotJSCell(iter, base); // base cell check linkSlowCase(iter); // base not array check - linkSlowCase(iter); // out of bounds - - Label slowPath = label(); + linkSlowCase(iter); // in vector check JITStubCall stubPutByValCall(this, cti_op_put_by_val); stubPutByValCall.addArgument(base); stubPutByValCall.addArgument(property); stubPutByValCall.addArgument(value); - Call call = stubPutByValCall.call(); - - m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath; - m_byValCompilationInfo[m_byValInstructionIndex].returnAddress = call; - m_byValInstructionIndex++; + stubPutByValCall.call(); } void JIT::emit_op_get_by_id(Instruction* currentInstruction) @@ -753,7 +616,7 @@ void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress) loadPtr(Address(regT0, JSCell::structureOffset()), regT2); emitArrayProfilingSiteForBytecodeIndex(regT2, regT3, stubInfo->bytecodeIndex); Jump failureCases1 = branchTest32(Zero, regT2, TrustedImm32(IsArray)); - Jump failureCases2 = branchTest32(Zero, regT2, TrustedImm32(IndexingShapeMask)); + Jump failureCases2 = branchTest32(Zero, regT2, TrustedImm32(HasArrayStorage)); // Checks out okay! - get the length from the storage loadPtr(Address(regT0, JSArray::butterflyOffset()), regT2); @@ -1162,24 +1025,24 @@ void JIT::compileGetDirectOffset(RegisterID base, RegisterID resultTag, Register ASSERT(sizeof(JSValue) == 8); if (finalObjectMode == MayBeFinal) { - Jump isInline = branch32(LessThan, offset, TrustedImm32(firstOutOfLineOffset)); + Jump isInline = branch32(LessThan, offset, TrustedImm32(inlineStorageCapacity)); loadPtr(Address(base, JSObject::butterflyOffset()), base); neg32(offset); Jump done = jump(); isInline.link(this); - addPtr(TrustedImmPtr(JSObject::offsetOfInlineStorage() - (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue)), base); + addPtr(TrustedImmPtr(JSObject::offsetOfInlineStorage() - (inlineStorageCapacity - 2) * sizeof(EncodedJSValue)), base); done.link(this); } else { #if !ASSERT_DISABLED - Jump isOutOfLine = branch32(GreaterThanOrEqual, offset, TrustedImm32(firstOutOfLineOffset)); + Jump isOutOfLine = branch32(GreaterThanOrEqual, offset, TrustedImm32(inlineStorageCapacity)); breakpoint(); isOutOfLine.link(this); #endif loadPtr(Address(base, JSObject::butterflyOffset()), base); neg32(offset); } - load32(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload) + (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue)), resultPayload); - load32(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag) + (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue)), resultTag); + load32(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload) + (inlineStorageCapacity - 2) * sizeof(EncodedJSValue)), resultPayload); + load32(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag) + (inlineStorageCapacity - 2) * sizeof(EncodedJSValue)), resultTag); } void JIT::emit_op_get_by_pname(Instruction* currentInstruction) @@ -1204,10 +1067,7 @@ void JIT::emit_op_get_by_pname(Instruction* currentInstruction) load32(addressFor(i), regT3); sub32(TrustedImm32(1), regT3); addSlowCase(branch32(AboveOrEqual, regT3, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_numCacheableSlots)))); - Jump inlineProperty = branch32(Below, regT3, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructureInlineCapacity))); - add32(TrustedImm32(firstOutOfLineOffset), regT3); - sub32(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructureInlineCapacity)), regT3); - inlineProperty.link(this); + add32(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_offsetBase)), regT3); compileGetDirectOffset(regT2, regT1, regT0, regT3); emitStore(dst, regT1, regT0); @@ -1238,7 +1098,7 @@ void JIT::emit_op_get_scoped_var(Instruction* currentInstruction) int index = currentInstruction[2].u.operand; int skip = currentInstruction[3].u.operand; - emitGetFromCallFrameHeaderPtr(JSStack::ScopeChain, regT2); + emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2); bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain(); ASSERT(skip || !checkTopLevel); if (checkTopLevel && skip--) { @@ -1267,7 +1127,7 @@ void JIT::emit_op_put_scoped_var(Instruction* currentInstruction) emitLoad(value, regT1, regT0); - emitGetFromCallFrameHeaderPtr(JSStack::ScopeChain, regT2); + emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2); bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain(); ASSERT(skip || !checkTopLevel); if (checkTopLevel && skip--) { diff --git a/Source/JavaScriptCore/jit/JITStubs.cpp b/Source/JavaScriptCore/jit/JITStubs.cpp index 1a2c654bc..da507838a 100644 --- a/Source/JavaScriptCore/jit/JITStubs.cpp +++ b/Source/JavaScriptCore/jit/JITStubs.cpp @@ -63,7 +63,6 @@ #include "RegExpObject.h" #include "RegExpPrototype.h" #include "Register.h" -#include "RepatchBuffer.h" #include "SamplingTool.h" #include "Strong.h" #include <wtf/StdLibExtras.h> @@ -225,7 +224,7 @@ COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x50, JITStackFrame_code_ extern "C" { - __declspec(naked) EncodedJSValue ctiTrampoline(void* code, JSStack*, CallFrame*, void* /*unused1*/, void* /*unused2*/, JSGlobalData*) + __declspec(naked) EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, void* /*unused1*/, void* /*unused2*/, JSGlobalData*) { __asm { push ebp; @@ -286,7 +285,7 @@ extern "C" { #define STACK_LENGTH 104 #elif CPU(SH4) #define SYMBOL_STRING(name) #name -/* code (r4), JSStack* (r5), CallFrame* (r6), void* unused1 (r7), void* unused2(sp), JSGlobalData (sp)*/ +/* code (r4), RegisterFile* (r5), CallFrame* (r6), void* unused1 (r7), void* unused2(sp), JSGlobalData (sp)*/ asm volatile ( ".text\n" @@ -459,7 +458,7 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n" "move $16,$6 # set callFrameRegister" "\n" "li $17,512 # set timeoutCheckRegister" "\n" "move $25,$4 # move executableAddress to t9" "\n" - "sw $5," STRINGIZE_VALUE_OF(REGISTER_FILE_OFFSET) "($29) # store JSStack to current stack" "\n" + "sw $5," STRINGIZE_VALUE_OF(REGISTER_FILE_OFFSET) "($29) # store registerFile to current stack" "\n" "lw $9," STRINGIZE_VALUE_OF(STACK_LENGTH + 20) "($29) # load globalData from previous stack" "\n" "jalr $25" "\n" "sw $9," STRINGIZE_VALUE_OF(GLOBAL_DATA_OFFSET) "($29) # store globalData to current stack" "\n" @@ -660,7 +659,7 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" #elif COMPILER(RVCT) && CPU(ARM_THUMB2) -__asm EncodedJSValue ctiTrampoline(void*, JSStack*, CallFrame*, void* /*unused1*/, void* /*unused2*/, JSGlobalData*) +__asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, void* /*unused1*/, void* /*unused2*/, JSGlobalData*) { PRESERVE8 sub sp, sp, # FIRST_STACK_ARGUMENT @@ -728,7 +727,7 @@ __asm void ctiOpThrowNotCaught() #elif COMPILER(RVCT) && CPU(ARM_TRADITIONAL) -__asm EncodedJSValue ctiTrampoline(void*, JSStack*, CallFrame*, void* /*unused1*/, void* /*unused2*/, JSGlobalData*) +__asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, void* /*unused1*/, void* /*unused2*/, JSGlobalData*) { ARM stmdb sp!, {r1-r3} @@ -797,7 +796,7 @@ JITThunks::JITThunks(JSGlobalData* globalData) ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR10) == PRESERVED_R10_OFFSET); ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR11) == PRESERVED_R11_OFFSET); - ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, stack) == REGISTER_FILE_OFFSET); + ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, registerFile) == REGISTER_FILE_OFFSET); // The fifth argument is the first item already on the stack. ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, unused1) == FIRST_STACK_ARGUMENT); @@ -816,7 +815,7 @@ JITThunks::JITThunks(JSGlobalData* globalData) ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedS2) == PRESERVED_S2_OFFSET); ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedReturnAddress) == PRESERVED_RETURN_ADDRESS_OFFSET); ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == THUNK_RETURN_ADDRESS_OFFSET); - ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, stack) == REGISTER_FILE_OFFSET); + ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, registerFile) == REGISTER_FILE_OFFSET); ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, globalData) == GLOBAL_DATA_OFFSET); #endif @@ -1050,7 +1049,7 @@ static NEVER_INLINE void returnToThrowTrampoline(JSGlobalData* globalData, Retur } while (0) // Helper function for JIT stubs that may throw an exception in the middle of -// processing a function call. This function rolls back the stack to +// processing a function call. This function rolls back the register file to // our caller, so exception processing can proceed from a valid state. template<typename T> static T throwExceptionFromOpCall(JITStackFrame& jitStackFrame, CallFrame* newCallFrame, ReturnAddressPtr& returnAddressSlot) { @@ -1360,12 +1359,12 @@ DEFINE_STUB_FUNCTION(int, timeout_check) return timeoutChecker.ticksUntilNextCheck(); } -DEFINE_STUB_FUNCTION(void*, stack_check) +DEFINE_STUB_FUNCTION(void*, register_file_check) { STUB_INIT_STACK_FRAME(stackFrame); CallFrame* callFrame = stackFrame.callFrame; - if (UNLIKELY(!stackFrame.stack->grow(&callFrame->registers()[callFrame->codeBlock()->m_numCalleeRegisters]))) + if (UNLIKELY(!stackFrame.registerFile->grow(&callFrame->registers()[callFrame->codeBlock()->m_numCalleeRegisters]))) return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS, createStackOverflowError(callFrame->callerFrame())); return callFrame; @@ -2192,7 +2191,7 @@ DEFINE_STUB_FUNCTION(void*, op_call_arityCheck) CallFrame* callFrame = stackFrame.callFrame; - CallFrame* newCallFrame = CommonSlowPaths::arityCheckFor(callFrame, stackFrame.stack, CodeForCall); + CallFrame* newCallFrame = CommonSlowPaths::arityCheckFor(callFrame, stackFrame.registerFile, CodeForCall); if (!newCallFrame) return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS, createStackOverflowError(callFrame->callerFrame())); @@ -2205,7 +2204,7 @@ DEFINE_STUB_FUNCTION(void*, op_construct_arityCheck) CallFrame* callFrame = stackFrame.callFrame; - CallFrame* newCallFrame = CommonSlowPaths::arityCheckFor(callFrame, stackFrame.stack, CodeForConstruct); + CallFrame* newCallFrame = CommonSlowPaths::arityCheckFor(callFrame, stackFrame.registerFile, CodeForConstruct); if (!newCallFrame) return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS, createStackOverflowError(callFrame->callerFrame())); @@ -2415,30 +2414,6 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_construct_NotJSConstruct) return returnValue; } -static JSValue getByVal( - CallFrame* callFrame, JSValue baseValue, JSValue subscript, ReturnAddressPtr returnAddress) -{ - if (LIKELY(baseValue.isCell() && subscript.isString())) { - if (JSValue result = baseValue.asCell()->fastGetOwnProperty(callFrame, asString(subscript)->value(callFrame))) - return result; - } - - if (subscript.isUInt32()) { - uint32_t i = subscript.asUInt32(); - if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) { - ctiPatchCallByReturnAddress(callFrame->codeBlock(), returnAddress, FunctionPtr(cti_op_get_by_val_string)); - return asString(baseValue)->getIndex(callFrame, i); - } - return baseValue.get(callFrame, i); - } - - if (isName(subscript)) - return baseValue.get(callFrame, jsCast<NameInstance*>(subscript.asCell())->privateName()); - - Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame)); - return baseValue.get(callFrame, property); -} - DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val) { STUB_INIT_STACK_FRAME(stackFrame); @@ -2448,56 +2423,35 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val) JSValue baseValue = stackFrame.args[0].jsValue(); JSValue subscript = stackFrame.args[1].jsValue(); - if (baseValue.isObject() && subscript.isInt32()) { - // See if it's worth optimizing this at all. - JSObject* object = asObject(baseValue); - bool didOptimize = false; - - unsigned bytecodeOffset = callFrame->bytecodeOffsetForNonDFGCode(); - ASSERT(bytecodeOffset); - ByValInfo& byValInfo = callFrame->codeBlock()->getByValInfo(bytecodeOffset - 1); - ASSERT(!byValInfo.stubRoutine); - - if (hasOptimizableIndexing(object->structure())) { - // Attempt to optimize. - JITArrayMode arrayMode = jitArrayModeForStructure(object->structure()); - if (arrayMode != byValInfo.arrayMode) { - JIT::compileGetByVal(&callFrame->globalData(), callFrame->codeBlock(), &byValInfo, STUB_RETURN_ADDRESS, arrayMode); - didOptimize = true; - } + if (LIKELY(baseValue.isCell() && subscript.isString())) { + if (JSValue result = baseValue.asCell()->fastGetOwnProperty(callFrame, asString(subscript)->value(callFrame))) { + CHECK_FOR_EXCEPTION(); + return JSValue::encode(result); } - - if (!didOptimize) { - // If we take slow path more than 10 times without patching then make sure we - // never make that mistake again. Or, if we failed to patch and we have some object - // that intercepts indexed get, then don't even wait until 10 times. For cases - // where we see non-index-intercepting objects, this gives 10 iterations worth of - // opportunity for us to observe that the get_by_val may be polymorphic. - if (++byValInfo.slowPathCount >= 10 - || object->structure()->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) { - // Don't ever try to optimize. - RepatchBuffer repatchBuffer(callFrame->codeBlock()); - repatchBuffer.relinkCallerToFunction(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_generic)); - } + } + + if (subscript.isUInt32()) { + uint32_t i = subscript.asUInt32(); + if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) { + ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_string)); + JSValue result = asString(baseValue)->getIndex(callFrame, i); + CHECK_FOR_EXCEPTION(); + return JSValue::encode(result); } + JSValue result = baseValue.get(callFrame, i); + CHECK_FOR_EXCEPTION(); + return JSValue::encode(result); } - - JSValue result = getByVal(callFrame, baseValue, subscript, STUB_RETURN_ADDRESS); - CHECK_FOR_EXCEPTION(); - return JSValue::encode(result); -} - -DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_generic) -{ - STUB_INIT_STACK_FRAME(stackFrame); - CallFrame* callFrame = stackFrame.callFrame; + if (isName(subscript)) { + JSValue result = baseValue.get(callFrame, jsCast<NameInstance*>(subscript.asCell())->privateName()); + CHECK_FOR_EXCEPTION(); + return JSValue::encode(result); + } - JSValue baseValue = stackFrame.args[0].jsValue(); - JSValue subscript = stackFrame.args[1].jsValue(); - - JSValue result = getByVal(callFrame, baseValue, subscript, STUB_RETURN_ADDRESS); - CHECK_FOR_EXCEPTION(); + Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame)); + JSValue result = baseValue.get(callFrame, property); + CHECK_FOR_EXCEPTION_AT_END(); return JSValue::encode(result); } @@ -2548,14 +2502,23 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_sub) return JSValue::encode(result); } -static void putByVal(CallFrame* callFrame, JSValue baseValue, JSValue subscript, JSValue value) +DEFINE_STUB_FUNCTION(void, op_put_by_val) { + STUB_INIT_STACK_FRAME(stackFrame); + + CallFrame* callFrame = stackFrame.callFrame; + JSGlobalData* globalData = stackFrame.globalData; + + JSValue baseValue = stackFrame.args[0].jsValue(); + JSValue subscript = stackFrame.args[1].jsValue(); + JSValue value = stackFrame.args[2].jsValue(); + if (LIKELY(subscript.isUInt32())) { uint32_t i = subscript.asUInt32(); if (baseValue.isObject()) { JSObject* object = asObject(baseValue); if (object->canSetIndexQuickly(i)) - object->setIndexQuickly(callFrame->globalData(), i, value); + object->setIndexQuickly(*globalData, i, value); else object->methodTable()->putByIndex(object, callFrame, i, value, callFrame->codeBlock()->isStrictMode()); } else @@ -2565,73 +2528,11 @@ static void putByVal(CallFrame* callFrame, JSValue baseValue, JSValue subscript, baseValue.put(callFrame, jsCast<NameInstance*>(subscript.asCell())->privateName(), value, slot); } else { Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame)); - if (!callFrame->globalData().exception) { // Don't put to an object if toString threw an exception. + if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception. PutPropertySlot slot(callFrame->codeBlock()->isStrictMode()); baseValue.put(callFrame, property, value, slot); } } -} - -DEFINE_STUB_FUNCTION(void, op_put_by_val) -{ - STUB_INIT_STACK_FRAME(stackFrame); - - CallFrame* callFrame = stackFrame.callFrame; - - JSValue baseValue = stackFrame.args[0].jsValue(); - JSValue subscript = stackFrame.args[1].jsValue(); - JSValue value = stackFrame.args[2].jsValue(); - - if (baseValue.isObject() && subscript.isInt32()) { - // See if it's worth optimizing at all. - JSObject* object = asObject(baseValue); - bool didOptimize = false; - - unsigned bytecodeOffset = callFrame->bytecodeOffsetForNonDFGCode(); - ASSERT(bytecodeOffset); - ByValInfo& byValInfo = callFrame->codeBlock()->getByValInfo(bytecodeOffset - 1); - ASSERT(!byValInfo.stubRoutine); - - if (hasOptimizableIndexing(object->structure())) { - // Attempt to optimize. - JITArrayMode arrayMode = jitArrayModeForStructure(object->structure()); - if (arrayMode != byValInfo.arrayMode) { - JIT::compilePutByVal(&callFrame->globalData(), callFrame->codeBlock(), &byValInfo, STUB_RETURN_ADDRESS, arrayMode); - didOptimize = true; - } - } - - if (!didOptimize) { - // If we take slow path more than 10 times without patching then make sure we - // never make that mistake again. Or, if we failed to patch and we have some object - // that intercepts indexed get, then don't even wait until 10 times. For cases - // where we see non-index-intercepting objects, this gives 10 iterations worth of - // opportunity for us to observe that the get_by_val may be polymorphic. - if (++byValInfo.slowPathCount >= 10 - || object->structure()->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) { - // Don't ever try to optimize. - RepatchBuffer repatchBuffer(callFrame->codeBlock()); - repatchBuffer.relinkCallerToFunction(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val_generic)); - } - } - } - - putByVal(callFrame, baseValue, subscript, value); - - CHECK_FOR_EXCEPTION_AT_END(); -} - -DEFINE_STUB_FUNCTION(void, op_put_by_val_generic) -{ - STUB_INIT_STACK_FRAME(stackFrame); - - CallFrame* callFrame = stackFrame.callFrame; - - JSValue baseValue = stackFrame.args[0].jsValue(); - JSValue subscript = stackFrame.args[1].jsValue(); - JSValue value = stackFrame.args[2].jsValue(); - - putByVal(callFrame, baseValue, subscript, value); CHECK_FOR_EXCEPTION_AT_END(); } @@ -2681,12 +2582,12 @@ DEFINE_STUB_FUNCTION(void*, op_load_varargs) STUB_INIT_STACK_FRAME(stackFrame); CallFrame* callFrame = stackFrame.callFrame; - JSStack* stack = stackFrame.stack; + RegisterFile* registerFile = stackFrame.registerFile; JSValue thisValue = stackFrame.args[0].jsValue(); JSValue arguments = stackFrame.args[1].jsValue(); int firstFreeRegister = stackFrame.args[2].int32(); - CallFrame* newCallFrame = loadVarargs(callFrame, stack, thisValue, arguments, firstFreeRegister); + CallFrame* newCallFrame = loadVarargs(callFrame, registerFile, thisValue, arguments, firstFreeRegister); if (!newCallFrame) VM_THROW_EXCEPTION(); return newCallFrame; @@ -3522,8 +3423,8 @@ MacroAssemblerCodeRef JITThunks::ctiStub(JSGlobalData* globalData, ThunkGenerato { CTIStubMap::AddResult entry = m_ctiStubMap.add(generator, MacroAssemblerCodeRef()); if (entry.isNewEntry) - entry.iterator->value = generator(globalData); - return entry.iterator->value; + entry.iterator->second = generator(globalData); + return entry.iterator->second; } NativeExecutable* JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function, NativeFunction constructor) diff --git a/Source/JavaScriptCore/jit/JITStubs.h b/Source/JavaScriptCore/jit/JITStubs.h index ecf415d1f..a4619c816 100644 --- a/Source/JavaScriptCore/jit/JITStubs.h +++ b/Source/JavaScriptCore/jit/JITStubs.h @@ -52,13 +52,13 @@ namespace JSC { class JSGlobalObject; class JSObject; class JSPropertyNameIterator; - class JSStack; class JSValue; class JSValueEncodedAsPointer; class NativeExecutable; class Profiler; class PropertySlot; class PutPropertySlot; + class RegisterFile; class RegExp; class Structure; @@ -101,7 +101,7 @@ namespace JSC { void* padding[2]; // Maintain 32-byte stack alignment (possibly overkill). void* code; - JSStack* stack; + RegisterFile* registerFile; CallFrame* callFrame; void* unused1; void* unused2; @@ -137,7 +137,7 @@ namespace JSC { void* savedEIP; void* code; - JSStack* stack; + RegisterFile* registerFile; CallFrame* callFrame; void* unused1; void* unused2; @@ -167,7 +167,7 @@ namespace JSC { void* preservedR11; // These arguments passed in r1..r3 (r0 contained the entry code pointed, which is not preserved) - JSStack* stack; + RegisterFile* registerFile; CallFrame* callFrame; // These arguments passed on the stack. @@ -196,7 +196,7 @@ namespace JSC { void* preservedR11; void* preservedLink; - JSStack* stack; + RegisterFile* registerFile; CallFrame* callFrame; void* unused1; @@ -228,7 +228,7 @@ namespace JSC { ReturnAddressPtr thunkReturnAddress; // These arguments passed in a1..a3 (a0 contained the entry code pointed, which is not preserved) - JSStack* stack; + RegisterFile* registerFile; CallFrame* callFrame; void* unused1; @@ -251,7 +251,7 @@ namespace JSC { void* savedR14; void* savedTimeoutReg; - JSStack* stack; + RegisterFile* registerFile; CallFrame* callFrame; JSValue* exception; void* unused1; @@ -284,7 +284,7 @@ namespace JSC { extern "C" void ctiVMThrowTrampoline(); extern "C" void ctiOpThrowNotCaught(); - extern "C" EncodedJSValue ctiTrampoline(void* code, JSStack*, CallFrame*, void* /*unused1*/, void* /*unused2*/, JSGlobalData*); + extern "C" EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, void* /*unused1*/, void* /*unused2*/, JSGlobalData*); #if ENABLE(DFG_JIT) extern "C" void ctiTrampolineEnd(); @@ -370,7 +370,6 @@ extern "C" { EncodedJSValue JIT_STUB cti_op_get_by_id_self_fail(STUB_ARGS_DECLARATION) WTF_INTERNAL; EncodedJSValue JIT_STUB cti_op_get_by_id_string_fail(STUB_ARGS_DECLARATION) WTF_INTERNAL; EncodedJSValue JIT_STUB cti_op_get_by_val(STUB_ARGS_DECLARATION) WTF_INTERNAL; - EncodedJSValue JIT_STUB cti_op_get_by_val_generic(STUB_ARGS_DECLARATION) WTF_INTERNAL; EncodedJSValue JIT_STUB cti_op_get_by_val_string(STUB_ARGS_DECLARATION) WTF_INTERNAL; EncodedJSValue JIT_STUB cti_op_in(STUB_ARGS_DECLARATION) WTF_INTERNAL; EncodedJSValue JIT_STUB cti_op_instanceof(STUB_ARGS_DECLARATION) WTF_INTERNAL; @@ -447,7 +446,6 @@ extern "C" { void JIT_STUB cti_op_put_by_id_direct_generic(STUB_ARGS_DECLARATION) WTF_INTERNAL; void JIT_STUB cti_op_put_by_index(STUB_ARGS_DECLARATION) WTF_INTERNAL; void JIT_STUB cti_op_put_by_val(STUB_ARGS_DECLARATION) WTF_INTERNAL; - void JIT_STUB cti_op_put_by_val_generic(STUB_ARGS_DECLARATION) WTF_INTERNAL; void JIT_STUB cti_op_put_getter_setter(STUB_ARGS_DECLARATION) WTF_INTERNAL; void JIT_STUB cti_op_put_global_var_check(STUB_ARGS_DECLARATION) WTF_INTERNAL; void JIT_STUB cti_op_tear_off_activation(STUB_ARGS_DECLARATION) WTF_INTERNAL; @@ -464,7 +462,7 @@ extern "C" { 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_stack_check(STUB_ARGS_DECLARATION) WTF_INTERNAL; + void* JIT_STUB cti_register_file_check(STUB_ARGS_DECLARATION) WTF_INTERNAL; void* JIT_STUB cti_vm_lazyLinkCall(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; diff --git a/Source/JavaScriptCore/jit/JSInterfaceJIT.h b/Source/JavaScriptCore/jit/JSInterfaceJIT.h index 8d9a0c800..52f1dd0b0 100644 --- a/Source/JavaScriptCore/jit/JSInterfaceJIT.h +++ b/Source/JavaScriptCore/jit/JSInterfaceJIT.h @@ -29,10 +29,10 @@ #include "BytecodeConventions.h" #include "JITCode.h" #include "JITStubs.h" -#include "JSStack.h" #include "JSString.h" #include "JSValue.h" #include "MacroAssembler.h" +#include "RegisterFile.h" #include <wtf/AlwaysInline.h> #include <wtf/Vector.h> diff --git a/Source/JavaScriptCore/jit/SpecializedThunkJIT.h b/Source/JavaScriptCore/jit/SpecializedThunkJIT.h index 560f7c833..0fe606476 100644 --- a/Source/JavaScriptCore/jit/SpecializedThunkJIT.h +++ b/Source/JavaScriptCore/jit/SpecializedThunkJIT.h @@ -40,7 +40,7 @@ namespace JSC { SpecializedThunkJIT(int expectedArgCount) { // Check that we have the expected number of arguments - m_failures.append(branch32(NotEqual, payloadFor(JSStack::ArgumentCount), TrustedImm32(expectedArgCount + 1))); + m_failures.append(branch32(NotEqual, payloadFor(RegisterFile::ArgumentCount), TrustedImm32(expectedArgCount + 1))); } void loadDoubleArgument(int argument, FPRegisterID dst, RegisterID scratch) @@ -83,7 +83,7 @@ namespace JSC { { if (src != regT0) move(src, regT0); - loadPtr(payloadFor(JSStack::CallerFrame, callFrameRegister), callFrameRegister); + loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister); ret(); } @@ -108,7 +108,7 @@ namespace JSC { lowNonZero.link(this); highNonZero.link(this); #endif - loadPtr(payloadFor(JSStack::CallerFrame, callFrameRegister), callFrameRegister); + loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister); ret(); } @@ -117,7 +117,7 @@ namespace JSC { if (src != regT0) move(src, regT0); tagReturnAsInt32(); - loadPtr(payloadFor(JSStack::CallerFrame, callFrameRegister), callFrameRegister); + loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister); ret(); } @@ -126,7 +126,7 @@ namespace JSC { if (src != regT0) move(src, regT0); tagReturnAsJSCell(); - loadPtr(payloadFor(JSStack::CallerFrame, callFrameRegister), callFrameRegister); + loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister); ret(); } |