RESOLVED FIXED Bug 123195
Make JSCells have 32-bit Structure pointers
https://bugs.webkit.org/show_bug.cgi?id=123195
Summary Make JSCells have 32-bit Structure pointers
Mark Hahnenberg
Reported 2013-10-22 20:10:21 PDT
This will free up 32 bits of space in JSCell headers, which we can use for other information like the IndexingType, JSType, JSTypeInfo type flags, and garbage collection metadata.
Attachments
Patch (154.04 KB, patch)
2013-10-22 20:21 PDT, Mark Hahnenberg
no flags
Patch (154.07 KB, patch)
2013-10-22 20:44 PDT, Mark Hahnenberg
no flags
Patch (302.52 KB, patch)
2013-10-25 12:31 PDT, Mark Hahnenberg
no flags
Patch (314.98 KB, patch)
2013-10-30 18:03 PDT, Mark Hahnenberg
no flags
Patch (320.07 KB, patch)
2013-10-30 18:56 PDT, Mark Hahnenberg
no flags
Patch (320.09 KB, patch)
2013-10-30 19:06 PDT, Mark Hahnenberg
no flags
Patch (315.86 KB, patch)
2013-10-31 13:01 PDT, Mark Hahnenberg
no flags
Patch (417.85 KB, patch)
2013-11-18 09:27 PST, Mark Hahnenberg
no flags
jsc benchmark results (35.94 KB, text/plain)
2013-11-18 09:32 PST, Mark Hahnenberg
no flags
rebase (417.82 KB, patch)
2013-11-18 09:38 PST, Mark Hahnenberg
no flags
Patch (431.08 KB, patch)
2014-02-25 12:58 PST, Mark Hahnenberg
no flags
Patch (454.09 KB, patch)
2014-02-25 19:25 PST, Mark Hahnenberg
no flags
Patch (455.51 KB, patch)
2014-02-26 12:06 PST, Mark Hahnenberg
no flags
Patch (454.87 KB, patch)
2014-02-26 13:26 PST, Mark Hahnenberg
no flags
Mark Hahnenberg
Comment 1 2013-10-22 20:21:24 PDT
EFL EWS Bot
Comment 2 2013-10-22 20:31:43 PDT
Mark Hahnenberg
Comment 3 2013-10-22 20:44:52 PDT
EFL EWS Bot
Comment 4 2013-10-22 20:52:26 PDT
Build Bot
Comment 5 2013-10-22 21:25:05 PDT
EFL EWS Bot
Comment 6 2013-10-23 01:13:35 PDT
kov's GTK+ EWS bot
Comment 7 2013-10-23 01:16:33 PDT
Mark Hahnenberg
Comment 8 2013-10-25 12:31:31 PDT
EFL EWS Bot
Comment 9 2013-10-25 12:41:42 PDT
EFL EWS Bot
Comment 10 2013-10-25 12:49:19 PDT
Build Bot
Comment 11 2013-10-25 13:14:24 PDT
kov's GTK+ EWS bot
Comment 12 2013-10-25 13:30:11 PDT
Mark Hahnenberg
Comment 13 2013-10-30 18:03:35 PDT
EFL EWS Bot
Comment 14 2013-10-30 18:14:06 PDT
Build Bot
Comment 15 2013-10-30 18:45:52 PDT
Mark Hahnenberg
Comment 16 2013-10-30 18:56:16 PDT
EFL EWS Bot
Comment 17 2013-10-30 19:05:20 PDT
Mark Hahnenberg
Comment 18 2013-10-30 19:06:35 PDT
Mark Hahnenberg
Comment 19 2013-10-31 13:01:29 PDT
Filip Pizlo
Comment 20 2013-10-31 13:45:02 PDT
Comment on attachment 215667 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=215667&action=review > Source/JavaScriptCore/jit/JSInterfaceJIT.h:402 > - ALWAYS_INLINE JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfNotType(RegisterID baseReg, RegisterID scratchReg, JSType type) > + ALWAYS_INLINE void JSInterfaceJIT::emitLoadStructure(RegisterID source, RegisterID dest, RegisterID scratch) > { > - loadPtr(Address(baseReg, JSCell::structureOffset()), scratchReg); > - return branch8(NotEqual, Address(scratchReg, Structure::typeInfoTypeOffset()), TrustedImm32(type)); > +#if USE(JSVALUE64) > + load32(MacroAssembler::Address(source, JSCell::structureIDOffset()), dest); > + loadPtr(vm()->heap.structureIDTable().base(), scratch); > + loadPtr(BaseIndex(scratch, dest, TimesEight), dest); > +#else > + UNUSED_PARAM(scratch); > + loadPtr(MacroAssembler::Address(source, JSCell::structureIDOffset()), dest); > +#endif > + } You could put this into AssemblyHelpers. > Source/JavaScriptCore/jit/UnusedPointer.h:35 > +#if USE(JSVALUE64) > +static const uintptr_t unusedPointer = 0x0; > +#else > static const uintptr_t unusedPointer = 0xd1e7beef; > +#endif Kill if possible. > Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm:304 > +# loadb Structure::m_indexingType[structure], scratch > +# storeb scratch, JSCell::m_indexingType[cell] > +# > +# loadb Structure::m_typeInfo + TypeInfo::m_flags[structure], scratch > +# storeb scratch, JSCell::m_flags[cell] > +# > +# loadb Structure::m_typeInfo + TypeInfo::m_type[structure], scratch > +# storeb scratch, JSCell::m_type[cell] > +# > +# storep structure, JSCell::m_structureID[cell] Delete. > Source/JavaScriptCore/llint/LowLevelInterpreter64.asm:229 > +# loadb Structure::m_indexingType[structure], scratch > +# storeb scratch, JSCell::m_indexingType[cell] > +# > +# loadb Structure::m_typeInfo + TypeInfo::m_flags[structure], scratch > +# storeb scratch, JSCell::m_flags[cell] > +# > +# loadb Structure::m_typeInfo + TypeInfo::m_type[structure], scratch > +# storeb scratch, JSCell::m_type[cell] > +# > +# loadi Structure::m_structureID[structure], scratch > +# storei scratch, JSCell::m_structureID[cell] Srsly bra
Mark Hahnenberg
Comment 21 2013-11-18 09:27:33 PST
Mark Hahnenberg
Comment 22 2013-11-18 09:32:46 PST
Created attachment 217204 [details] jsc benchmark results These are the benchmark results for this latest patch. Overall a slight slowdown. Sunspider and kraken are both 1-2% slower, v8v7 is ~0.5% faster, octane is neutral. 3d-cube seems to be the largest overall contributor to the slowdown in sunspider and especially in longspider (~30% slowdown).
Mark Hahnenberg
Comment 23 2013-11-18 09:38:44 PST
Build Bot
Comment 24 2013-11-18 10:11:08 PST
Build Bot
Comment 25 2013-11-18 10:16:34 PST
Geoffrey Garen
Comment 26 2013-11-18 10:59:18 PST
Comment on attachment 217205 [details] rebase View in context: https://bugs.webkit.org/attachment.cgi?id=217205&action=review > Source/JavaScriptCore/runtime/VM.h:535 > + inline VM* VM::currentVM() > + { > +#if USE(PTHREAD_GETSPECIFIC_DIRECT) > + return reinterpret_cast<VM*>(pthread_getspecific(s_currentVM)); > +#else > + return reinterpret_cast<VM*>(WTF::threadSpecificGet(s_currentVM)); > +#endif > + } > + > + inline void VM::setCurrentVM(VM* vm) > + { > +#if USE(PTHREAD_GETSPECIFIC_DIRECT) > + pthread_setspecific(s_currentVM, reinterpret_cast<void*>(vm)); > +#else > + WTF::threadSpecificSet(s_currentVM, reinterpret_cast<void*>(vm)); > +#endif > + } You want the _direct variant of pthread_getspecific and pthread_setspecific. That's the inlined version.
Geoffrey Garen
Comment 27 2013-11-18 11:00:15 PST
> Overall a slight slowdown. Sunspider and kraken are both 1-2% slower.... What's your plan for this?
Mark Hahnenberg
Comment 28 2014-02-25 12:58:48 PST
Filip Pizlo
Comment 29 2014-02-25 13:38:43 PST
Comment on attachment 225174 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=225174&action=review LGTM, but make those changes. > Source/JavaScriptCore/assembler/MacroAssemblerARM64.h:2228 > + ALWAYS_INLINE Jump branchPtrWithPatch(RelationalCondition cond, Address left, DataLabel32& dataLabel, TrustedImm32 initialRightValue = TrustedImm32(0)) > + { > + dataLabel = DataLabel32(this); > + moveWithPatch(initialRightValue, getCachedDataTempRegisterIDAndInvalidate()); > + return branch32(cond, left, dataTempRegister); > + } Rename to branch32WithPatch > Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp:4019 > - m_out.storePtr(structure, result, m_heaps.JSCell_structure); > + LValue structureID = m_out.load32(structure, m_heaps.Structure_structureID); > + LValue indexingType = m_out.load8(structure, m_heaps.Structure_indexingType); > + LValue typeInfoType = m_out.load8(structure, m_heaps.Structure_typeInfoType); > + LValue typeInfoFlags = m_out.load8(structure, m_heaps.Structure_typeInfoFlags); > + > + m_out.store32(structureID, result, m_heaps.JSCell_structureID); > + m_out.store8(indexingType, result, m_heaps.JSCell_indexingType); > + m_out.store8(typeInfoType, result, m_heaps.JSCell_typeInfoType); > + m_out.store8(typeInfoFlags, result, m_heaps.JSCell_typeInfoFlags); > + m_out.store8(m_out.constInt8(0), result, m_heaps.JSCell_gcData); The common case is that we're passing a constant structure. Factor this in such a way that if structure is a constant, this doesn't emit loads. > Source/JavaScriptCore/jit/UnusedPointer.h:35 > +#if USE(JSVALUE64) > +static const uintptr_t unusedPointer = 0x0; > +#else > static const uintptr_t unusedPointer = 0xd1e7beef; > +#endif Can we arrange to keep diet beef as the unused pointer? > Source/JavaScriptCore/runtime/JSCellInlines.h:95 > +inline IndexingType JSCell::indexingType() const > +{ > + return (*reinterpret_cast<const uint64_t*>(this) & 0x000000ff00000000) >> 32; > } Web template framework? > Source/JavaScriptCore/runtime/Structure.h:510 > + // These need to be properly aligned at the beginning of the 'Structure' > + // part of the object. > + StructureID m_structureID; > + IndexingType m_indexingType; > + TypeInfo m_typeInfo; Unionify.
Mark Hahnenberg
Comment 30 2014-02-25 19:25:58 PST
Filip Pizlo
Comment 31 2014-02-25 19:31:34 PST
(In reply to comment #30) > Created an attachment (id=225214) [details] > Patch Can has description of what changed? /me doesn't want to read the whole patch again.
Mark Hahnenberg
Comment 32 2014-02-25 19:35:33 PST
(In reply to comment #31) > (In reply to comment #30) > > Created an attachment (id=225214) [details] [details] > > Patch > > Can has description of what changed? > > /me doesn't want to read the whole patch again. The biggest change is that I added a StructureIDBlob class to encapsulate most of the crazy related to loading the blob out of the Structure during object initialization. It basically splits the TypeInfo in half (inlineTypeFlags and outOfLineTypeFlags), which you can recombine at any point to get a TypeInfo back. Also fixing some of your other comments, and trying to get all the ports building :-)
Sam Weinig
Comment 33 2014-02-26 09:15:35 PST
Comment on attachment 225214 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=225214&action=review > Source/JavaScriptCore/runtime/JSCellInlines.h:112 > + Structure* structure = cell->structure(); > + visitor.appendUnbarrieredPointer(&structure); Seems unfortunate to have to do the expensive JS::structure(), could we pull the VM& from the SlotVisitor? > Source/JavaScriptCore/runtime/JSDestructibleObject.h:37 > if (MarkedBlock::blockFor(this)->destructorType() == MarkedBlock::Normal) > return static_cast<const JSDestructibleObject*>(this)->classInfo(); > -#if ENABLE(GC_VALIDATION) > - return m_structure.unvalidatedGet()->classInfo(); > -#else > - return m_structure->classInfo(); > -#endif > + return structure()->classInfo(); > } Since you are already doing MarkedBlock::blockFor(this), can you pull the Heap (and then the VM&) out of it instead of repeating the same work in structure()? > Source/JavaScriptCore/runtime/JSFunction.cpp:396 > + thisObject->methodTable(exec->vm())->getOwnPropertySlot(thisObject, exec, exec->propertyNames().prototype, slot); You could probably reduce the generated code size here by pulling the VM& into a local and using it for things like propertyNames(), which otherwise will probably repeat the load. > Source/JavaScriptCore/runtime/JSObject.cpp:657 > + Structure* structure = this->structure(); You've got the VM, why not use it?
Csaba Osztrogonác
Comment 34 2014-02-26 09:58:55 PST
Comment on attachment 225214 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=225214&action=review > Source/JavaScriptCore/assembler/X86Assembler.h:2079 > + const int instructionSize = 6; // REX MOV IMM32 It should be unsigned to fix the EFL build. It is enough to make EFL build happy.
Mark Hahnenberg
Comment 35 2014-02-26 12:06:33 PST
Mark Hahnenberg
Comment 36 2014-02-26 12:07:26 PST
(In reply to comment #35) > Created an attachment (id=225275) [details] > Patch No major changes, just fixing builds and review feedback.
Filip Pizlo
Comment 37 2014-02-26 12:12:04 PST
Comment on attachment 225275 [details] Patch R=me
Mark Hahnenberg
Comment 38 2014-02-26 13:26:27 PST
Mark Hahnenberg
Comment 39 2014-02-26 17:22:02 PST
Ryosuke Niwa
Comment 40 2014-02-26 18:32:52 PST
Looks like this change introduced a crash inside Indentifier::add. I'm hitting it on a few hundred tests now.
Ryosuke Niwa
Comment 41 2014-02-26 18:33:53 PST
identifierTable is null inside JSC::Identifier::add.
Mark Hahnenberg
Comment 42 2014-02-26 18:35:00 PST
(In reply to comment #41) > identifierTable is null inside JSC::Identifier::add. Odd. I was passing all tests prior to landing. Bug? Backtrace?
Ryosuke Niwa
Comment 43 2014-02-26 18:44:05 PST
(In reply to comment #42) > (In reply to comment #41) > > identifierTable is null inside JSC::Identifier::add. > > Odd. I was passing all tests prior to landing. Bug? Backtrace? Sam suggested I might be hitting a stale build file issue so I'm doing a full clean build now. Will report back traces when that's done.
Ryosuke Niwa
Comment 44 2014-02-26 18:53:59 PST
(In reply to comment #43) > (In reply to comment #42) > > (In reply to comment #41) > > > identifierTable is null inside JSC::Identifier::add. > > > > Odd. I was passing all tests prior to landing. Bug? Backtrace? > > Sam suggested I might be hitting a stale build file issue so I'm doing a full clean build now. Will report back traces when that's done. Looks like this was it. Sorry about the false positive :(
Mark Hahnenberg
Comment 45 2014-02-26 18:54:47 PST
(In reply to comment #44) > (In reply to comment #43) > > (In reply to comment #42) > > > (In reply to comment #41) > > > > identifierTable is null inside JSC::Identifier::add. > > > > > > Odd. I was passing all tests prior to landing. Bug? Backtrace? > > > > Sam suggested I might be hitting a stale build file issue so I'm doing a full clean build now. Will report back traces when that's done. > > Looks like this was it. Sorry about the false positive :( Whew! :-)
Note You need to log in before you can comment on or make changes to this bug.