diff options
Diffstat (limited to 'Source/JavaScriptCore')
44 files changed, 468 insertions, 289 deletions
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog index 69c052433..c3501e8f8 100644 --- a/Source/JavaScriptCore/ChangeLog +++ b/Source/JavaScriptCore/ChangeLog @@ -1,20 +1,185 @@ -2012-06-13 Patrick Gansterer <paroga@webkit.org> +2012-07-23 Patrick Gansterer <paroga@webkit.org> - [WIN] Remove dependency on pthread from MachineStackMarker - https://bugs.webkit.org/show_bug.cgi?id=68429 + Move GregorianDateTime from JSC to WTF namespace + https://bugs.webkit.org/show_bug.cgi?id=91948 - Reviewed by NOBODY (OOPS!). + Reviewed by Geoffrey Garen. - Implement pthread TLS functionality with native windows functions. + Moving GregorianDateTime into the WTF namespace allows us to us to + use it in WebCore too. The new class has the same behaviour as the + old struct. Only the unused timeZone member has been removed. - * heap/MachineStackMarker.cpp: Use the new functions instead of pthread directly. - * heap/MachineStackMarker.h: - * wtf/ThreadSpecific.h: - (WTF::ThreadSpecificKeyCreate): Added wrapper around pthread_key_create. - (WTF::ThreadSpecificKeyDelete): Added wrapper around pthread_key_delete. - (WTF::ThreadSpecificSet): Added wrapper around pthread_setspecific. - (WTF::ThreadSpecificGet): Added wrapper around pthread_getspecific. - * wtf/ThreadSpecificWin.cpp: + * runtime/DateConstructor.cpp: + * runtime/DateConversion.cpp: + * runtime/DateConversion.h: + * runtime/DateInstance.h: + * runtime/DatePrototype.cpp: + * runtime/JSDateMath.cpp: + * runtime/JSDateMath.h: + +2012-07-23 Filip Pizlo <fpizlo@apple.com> + + Property storage should grow in reverse address direction, to support butterflies + https://bugs.webkit.org/show_bug.cgi?id=91788 + + Reviewed by Geoffrey Garen. + + Changes property storage to grow to the left, and changes the property storage pointer to point + one 8-byte word (i.e. JSValue) to the right of the first value in the storage. + + Also improved debug support somewhat, by adding a describe() function to the jsc command-line, + and a slow mode of object access in LLInt. + + * assembler/ARMv7Assembler.h: + (JSC::ARMv7Assembler::repatchCompact): + * assembler/MacroAssemblerARMv7.h: + (MacroAssemblerARMv7): + (JSC::MacroAssemblerARMv7::isCompactPtrAlignedAddressOffset): + (JSC::MacroAssemblerARMv7::load32WithCompactAddressOffsetPatch): + * assembler/MacroAssemblerX86Common.h: + (JSC::MacroAssemblerX86Common::isCompactPtrAlignedAddressOffset): + (JSC::MacroAssemblerX86Common::repatchCompact): + * assembler/X86Assembler.h: + (JSC::X86Assembler::repatchCompact): + * bytecode/CodeBlock.cpp: + (JSC::dumpStructure): + * bytecode/GetByIdStatus.h: + (JSC::GetByIdStatus::GetByIdStatus): + * dfg/DFGOperations.cpp: + * dfg/DFGOperations.h: + * dfg/DFGRepatch.cpp: + (JSC::DFG::tryCacheGetByID): + (JSC::DFG::emitPutTransitionStub): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compileAllocatePropertyStorage): + (JSC::DFG::SpeculativeJIT::compileReallocatePropertyStorage): + * dfg/DFGSpeculativeJIT.h: + (JSC::DFG::SpeculativeJIT::callOperation): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * heap/ConservativeRoots.cpp: + (JSC::ConservativeRoots::genericAddPointer): + * heap/CopiedSpace.h: + (CopiedSpace): + * heap/CopiedSpaceInlineMethods.h: + (JSC::CopiedSpace::pinIfNecessary): + (JSC): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::compileGetDirectOffset): + * jit/JITPropertyAccess32_64.cpp: + (JSC::JIT::compileGetDirectOffset): + * jit/JITStubs.cpp: + (JSC::JITThunks::tryCacheGetByID): + * jsc.cpp: + (GlobalObject::finishCreation): + (functionDescribe): + * llint/LLIntCommon.h: + * llint/LLIntSlowPaths.cpp: + (JSC::LLInt::LLINT_SLOW_PATH_DECL): + * llint/LowLevelInterpreter32_64.asm: + * llint/LowLevelInterpreter64.asm: + * runtime/JSObject.cpp: + (JSC::JSObject::visitChildren): + (JSC::JSFinalObject::visitChildren): + (JSC::JSObject::growOutOfLineStorage): + * runtime/JSObject.h: + (JSC::JSObject::getDirectLocation): + (JSC::JSObject::offsetForLocation): + * runtime/JSValue.h: + (JSValue): + * runtime/PropertyOffset.h: + (JSC::offsetInOutOfLineStorage): + +2012-07-23 Filip Pizlo <fpizlo@apple.com> + + DFG is too aggressive in performing the specific value optimization on loads + https://bugs.webkit.org/show_bug.cgi?id=92034 + + Reviewed by Mark Hahnenberg. + + This ensures that we don't do optimizations based on a structure having a specific + value, if there is no way to detect that the value is despecified. This is the + case for dictionaries, since despecifying a value in a dictionary does not lead to + a transition and so cannot be caught by either structure checks or structure + transition watchpoints. + + * bytecode/GetByIdStatus.cpp: + (JSC::GetByIdStatus::computeFromLLInt): + (JSC::GetByIdStatus::computeForChain): + (JSC::GetByIdStatus::computeFor): + * bytecode/ResolveGlobalStatus.cpp: + (JSC::computeForStructure): + +2012-07-23 Filip Pizlo <fpizlo@apple.com> + + REGRESSION(r123169): It made fast/js/dfg-inline-arguments-use-from-uninlined-code.html fail on 32 bit platforms + https://bugs.webkit.org/show_bug.cgi?id=92002 + + Reviewed by Mark Hahnenberg. + + In the process of changing the nature of local variable typing, I forgot to modify one of the places where + we glue the DFG's notion of variable prediction to the runtime's notion of variable tagging. + + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compile): + +2012-07-23 Simon Fraser <simon.fraser@apple.com> + + Part 2 of: Implement sticky positioning + https://bugs.webkit.org/show_bug.cgi?id=90046 + + Reviewed by Ojan Vafai. + + Turn on ENABLE_CSS_STICKY_POSITION. + + * Configurations/FeatureDefines.xcconfig: + +2012-07-23 Patrick Gansterer <paroga@webkit.org> + + Move JSC::parseDate() from DateConversion to JSDateMath + https://bugs.webkit.org/show_bug.cgi?id=91982 + + Reviewed by Geoffrey Garen. + + Moveing this function into the other files removes the dependency + on JSC spcific classes in DateConversion.{cpp|h}. + + * runtime/DateConversion.cpp: + * runtime/DateConversion.h: + (JSC): + * runtime/JSDateMath.cpp: + (JSC::parseDate): + (JSC): + * runtime/JSDateMath.h: + (JSC): + +2012-07-23 Simon Fraser <simon.fraser@apple.com> + + Part 1 of: Implement sticky positioning + https://bugs.webkit.org/show_bug.cgi?id=90046 + + Reviewed by Ojan Vafai. + + Add ENABLE_CSS_STICKY_POSITION, defaulting to off initially. + + Sort the ENABLE_CSS lines in the file. Make sure all the flags + are in FEATURE_DEFINES. + + * Configurations/FeatureDefines.xcconfig: + +2012-07-23 Yong Li <yoli@rim.com> + + [BlackBerry] Implement GCActivityCallback with platform timer + https://bugs.webkit.org/show_bug.cgi?id=90175 + + Reviewed by Rob Buis. + + Use JSLock when performing GC to avoid assertions. + + * runtime/GCActivityCallbackBlackBerry.cpp: + (JSC::DefaultGCActivityCallback::doWork): 2012-07-23 Kent Tamura <tkent@chromium.org> diff --git a/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig b/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig index 31853f34c..0a26e46ff 100644 --- a/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig +++ b/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig @@ -37,14 +37,15 @@ ENABLE_ANIMATION_API = ; ENABLE_BLOB = ENABLE_BLOB; ENABLE_CHANNEL_MESSAGING = ENABLE_CHANNEL_MESSAGING; ENABLE_CSP_NEXT = ; -ENABLE_CSS3_FLEXBOX = ENABLE_CSS3_FLEXBOX; ENABLE_CSS_EXCLUSIONS = ENABLE_CSS_EXCLUSIONS; ENABLE_CSS_FILTERS = ENABLE_CSS_FILTERS; -ENABLE_CSS_SHADERS = ENABLE_CSS_SHADERS; ENABLE_CSS_IMAGE_ORIENTATION = ; ENABLE_CSS_IMAGE_RESOLUTION = ; ENABLE_CSS_REGIONS = ENABLE_CSS_REGIONS; +ENABLE_CSS_SHADERS = ENABLE_CSS_SHADERS; +ENABLE_CSS_STICKY_POSITION = ENABLE_CSS_STICKY_POSITION; ENABLE_CSS_VARIABLES = ; +ENABLE_CSS3_FLEXBOX = ENABLE_CSS3_FLEXBOX; ENABLE_CUSTOM_SCHEME_HANDLER = ; ENABLE_DASHBOARD_SUPPORT = $(ENABLE_DASHBOARD_SUPPORT_$(REAL_PLATFORM_NAME)); ENABLE_DASHBOARD_SUPPORT_macosx = ENABLE_DASHBOARD_SUPPORT; @@ -134,4 +135,4 @@ ENABLE_WEB_TIMING = ; ENABLE_WORKERS = ENABLE_WORKERS; ENABLE_XSLT = ENABLE_XSLT; -FEATURE_DEFINES = $(ENABLE_3D_RENDERING) $(ENABLE_ACCELERATED_2D_CANVAS) $(ENABLE_ANIMATION_API) $(ENABLE_BLOB) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CSP_NEXT) $(ENABLE_CSS3_FLEXBOX) $(ENABLE_CSS_EXCLUSIONS) $(ENABLE_CSS_FILTERS) $(ENABLE_CSS_IMAGE_ORIENTATION) $(ENABLE_CSS_IMAGE_RESOLUTION) $(ENABLE_CSS_REGIONS) $(ENABLE_CSS_SHADERS) $(ENABLE_CSS_VARIABLES) $(ENABLE_CUSTOM_SCHEME_HANDLER) $(ENABLE_DASHBOARD_SUPPORT) $(ENABLE_DATALIST_ELEMENT) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS_ELEMENT) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DIALOG_ELEMENT) $(ENABLE_DIRECTORY_UPLOAD) $(ENABLE_FILE_SYSTEM) $(ENABLE_FILTERS) $(ENABLE_FULLSCREEN_API) $(ENABLE_GAMEPAD) $(ENABLE_GEOLOCATION) $(ENABLE_HIGH_DPI_CANVAS) $(ENABLE_ICONDATABASE) $(ENABLE_IFRAME_SEAMLESS) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INPUT_TYPE_COLOR) $(ENABLE_INPUT_SPEECH) $(ENABLE_INPUT_TYPE_DATE) $(ENABLE_INPUT_TYPE_DATETIME) $(ENABLE_INPUT_TYPE_DATETIMELOCAL) $(ENABLE_INPUT_TYPE_MONTH) $(ENABLE_INPUT_TYPE_TIME) $(ENABLE_INPUT_TYPE_WEEK) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_LEGACY_CSS_VENDOR_PREFIXES) $(ENABLE_LEGACY_NOTIFICATIONS) $(ENABLE_LINK_PREFETCH) $(ENABLE_LINK_PRERENDER) $(ENABLE_MATHML) $(ENABLE_MEDIA_SOURCE) $(ENABLE_MEDIA_STATISTICS) $(ENABLE_METER_ELEMENT) $(ENABLE_MICRODATA) $(ENABLE_MUTATION_OBSERVERS) $(ENABLE_NOTIFICATIONS) $(ENABLE_PAGE_VISIBILITY_API) $(ENABLE_PROGRESS_ELEMENT) $(ENABLE_QUOTA) $(ENABLE_REGISTER_PROTOCOL_HANDLER) $(ENABLE_REQUEST_ANIMATION_FRAME) $(ENABLE_SCRIPTED_SPEECH) $(ENABLE_SHADOW_DOM) $(ENABLE_SHARED_WORKERS) $(ENABLE_SQL_DATABASE) $(ENABLE_STYLE_SCOPED) $(ENABLE_SVG) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_TEXT_AUTOSIZING) $(ENABLE_TEXT_NOTIFICATIONS_ONLY) $(ENABLE_TOUCH_ICON_LOADING) $(ENABLE_UNDO_MANAGER) $(ENABLE_VIDEO) $(ENABLE_VIDEO_TRACK) $(ENABLE_WEBGL) $(ENABLE_WEB_AUDIO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WEB_TIMING) $(ENABLE_WORKERS) $(ENABLE_XSLT); +FEATURE_DEFINES = $(ENABLE_3D_RENDERING) $(ENABLE_ACCELERATED_2D_CANVAS) $(ENABLE_ANIMATION_API) $(ENABLE_BLOB) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CSP_NEXT) $(ENABLE_CSS_BOX_DECORATION_BREAK) $(ENABLE_CSS_EXCLUSIONS) $(ENABLE_CSS_FILTERS) $(ENABLE_CSS_IMAGE_ORIENTATION) $(ENABLE_CSS_IMAGE_RESOLUTION) $(ENABLE_CSS_REGIONS) $(ENABLE_CSS_SHADERS) $(ENABLE_CSS_STICKY_POSITION) $(ENABLE_CSS_VARIABLES) $(ENABLE_CSS3_FLEXBOX) $(ENABLE_CUSTOM_SCHEME_HANDLER) $(ENABLE_DASHBOARD_SUPPORT) $(ENABLE_DATALIST_ELEMENT) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS_ELEMENT) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DIALOG_ELEMENT) $(ENABLE_DIRECTORY_UPLOAD) $(ENABLE_FILE_SYSTEM) $(ENABLE_FILTERS) $(ENABLE_FULLSCREEN_API) $(ENABLE_GAMEPAD) $(ENABLE_GEOLOCATION) $(ENABLE_HIGH_DPI_CANVAS) $(ENABLE_ICONDATABASE) $(ENABLE_IFRAME_SEAMLESS) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INPUT_SPEECH) $(ENABLE_INPUT_TYPE_COLOR) $(ENABLE_INPUT_TYPE_DATE) $(ENABLE_INPUT_TYPE_DATETIME) $(ENABLE_INPUT_TYPE_DATETIMELOCAL) $(ENABLE_INPUT_TYPE_MONTH) $(ENABLE_INPUT_TYPE_TIME) $(ENABLE_INPUT_TYPE_WEEK) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_LEGACY_CSS_VENDOR_PREFIXES) $(ENABLE_LEGACY_NOTIFICATIONS) $(ENABLE_LINK_PREFETCH) $(ENABLE_LINK_PRERENDER) $(ENABLE_MATHML) $(ENABLE_MEDIA_SOURCE) $(ENABLE_MEDIA_STATISTICS) $(ENABLE_METER_ELEMENT) $(ENABLE_MHTML) $(ENABLE_MICRODATA) $(ENABLE_MUTATION_OBSERVERS) $(ENABLE_NOTIFICATIONS) $(ENABLE_PAGE_VISIBILITY_API) $(ENABLE_PROGRESS_ELEMENT) $(ENABLE_QUOTA) $(ENABLE_REGISTER_PROTOCOL_HANDLER) $(ENABLE_REQUEST_ANIMATION_FRAME) $(ENABLE_SCRIPTED_SPEECH) $(ENABLE_SHADOW_DOM) $(ENABLE_SHARED_WORKERS) $(ENABLE_SQL_DATABASE) $(ENABLE_STYLE_SCOPED) $(ENABLE_SVG) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_TEXT_AUTOSIZING) $(ENABLE_TEXT_NOTIFICATIONS_ONLY) $(ENABLE_TOUCH_ICON_LOADING) $(ENABLE_UNDO_MANAGER) $(ENABLE_VIDEO) $(ENABLE_VIDEO_TRACK) $(ENABLE_WEBGL) $(ENABLE_WEB_AUDIO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WEB_TIMING) $(ENABLE_WORKERS) $(ENABLE_XSLT); diff --git a/Source/JavaScriptCore/Configurations/Version.xcconfig b/Source/JavaScriptCore/Configurations/Version.xcconfig index 39ad1b2be..daf808e05 100644 --- a/Source/JavaScriptCore/Configurations/Version.xcconfig +++ b/Source/JavaScriptCore/Configurations/Version.xcconfig @@ -22,7 +22,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MAJOR_VERSION = 537; -MINOR_VERSION = 2; +MINOR_VERSION = 3; TINY_VERSION = 0; FULL_VERSION = $(MAJOR_VERSION).$(MINOR_VERSION); diff --git a/Source/JavaScriptCore/JavaScriptCore.pri b/Source/JavaScriptCore/JavaScriptCore.pri index f6580c51f..380bbaf1b 100644 --- a/Source/JavaScriptCore/JavaScriptCore.pri +++ b/Source/JavaScriptCore/JavaScriptCore.pri @@ -34,6 +34,12 @@ INCLUDEPATH += \ win32-* { LIBS += -lwinmm + + win32-g++* { + LIBS += -lpthreadGC2 + } else:win32-msvc* { + LIBS += -lpthreadVC2 + } } wince* { diff --git a/Source/JavaScriptCore/assembler/ARMv7Assembler.h b/Source/JavaScriptCore/assembler/ARMv7Assembler.h index 96c4f096c..e9b9fcc50 100644 --- a/Source/JavaScriptCore/assembler/ARMv7Assembler.h +++ b/Source/JavaScriptCore/assembler/ARMv7Assembler.h @@ -2095,11 +2095,24 @@ public: setInt32(where, value); } - static void repatchCompact(void* where, int32_t value) + static void repatchCompact(void* where, int32_t offset) { - ASSERT(value >= 0); - ASSERT(ARMThumbImmediate::makeUInt12(value).isUInt7()); - setUInt7ForLoad(where, ARMThumbImmediate::makeUInt12(value)); + ASSERT(offset >= -255 && offset <= 255); + + bool add = true; + if (offset < 0) { + add = false; + offset = -offset; + } + + offset |= (add << 9); + offset |= (1 << 10); + offset |= (1 << 11); + + uint16_t* location = reinterpret_cast<uint16_t*>(where); + location[1] &= ~((1 << 12) - 1); + location[1] |= offset; + cacheFlush(location, sizeof(uint16_t) * 2); } static void repatchPointer(void* where, void* value) diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h b/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h index cf6f02ca9..183e8f980 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h @@ -53,10 +53,12 @@ public: typedef ARMv7Assembler::LinkRecord LinkRecord; typedef ARMv7Assembler::JumpType JumpType; typedef ARMv7Assembler::JumpLinkType JumpLinkType; - // Magic number is the biggest useful offset we can get on ARMv7 with - // a LDR_imm_T2 encoding - static const int MaximumCompactPtrAlignedAddressOffset = 124; - + + static bool isCompactPtrAlignedAddressOffset(ptrdiff_t value) + { + return value >= -255 && value <= 255; + } + Vector<LinkRecord>& jumpsToLink() { return m_assembler.jumpsToLink(); } void* unlinkedCode() { return m_assembler.unlinkedCode(); } bool canCompact(JumpType jumpType) { return m_assembler.canCompact(jumpType); } @@ -642,26 +644,14 @@ public: return label; } - // FIXME: we should be able to plant a compact load relative to/from any base/dest register. DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest) { RegisterID base = address.base; - if (base >= ARMRegisters::r8) { - move(base, addressTempRegister); - base = addressTempRegister; - } - DataLabelCompact label(this); - ASSERT(address.offset >= 0); - ASSERT(address.offset <= MaximumCompactPtrAlignedAddressOffset); - ASSERT(ARMThumbImmediate::makeUInt12(address.offset).isUInt7()); + ASSERT(isCompactPtrAlignedAddressOffset(address.offset)); - if (dest >= ARMRegisters::r8) { - m_assembler.ldrCompact(addressTempRegister, base, ARMThumbImmediate::makeUInt12(address.offset)); - move(addressTempRegister, dest); - } else - m_assembler.ldrCompact(dest, base, ARMThumbImmediate::makeUInt12(address.offset)); + m_assembler.ldr(dest, base, address.offset, true, false); return label; } diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h b/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h index 432489dbc..115b337f7 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h @@ -47,7 +47,10 @@ public: typedef X86Assembler::FPRegisterID FPRegisterID; typedef X86Assembler::XMMRegisterID XMMRegisterID; - static const int MaximumCompactPtrAlignedAddressOffset = 127; + static bool isCompactPtrAlignedAddressOffset(ptrdiff_t value) + { + return value >= -128 && value <= 127; + } enum RelationalCondition { Equal = X86Assembler::ConditionE, @@ -494,8 +497,7 @@ public: static void repatchCompact(CodeLocationDataLabelCompact dataLabelCompact, int32_t value) { - ASSERT(value >= 0); - ASSERT(value < MaximumCompactPtrAlignedAddressOffset); + ASSERT(isCompactPtrAlignedAddressOffset(value)); AssemblerType_T::repatchCompact(dataLabelCompact.dataLocation(), value); } diff --git a/Source/JavaScriptCore/assembler/X86Assembler.h b/Source/JavaScriptCore/assembler/X86Assembler.h index fc1c27245..adaee4bc0 100644 --- a/Source/JavaScriptCore/assembler/X86Assembler.h +++ b/Source/JavaScriptCore/assembler/X86Assembler.h @@ -1829,7 +1829,7 @@ public: static void repatchCompact(void* where, int32_t value) { - ASSERT(value >= 0); + ASSERT(value >= std::numeric_limits<int8_t>::min()); ASSERT(value <= std::numeric_limits<int8_t>::max()); setInt8(where, value); } diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp index 363efa28a..5374a537a 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp +++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp @@ -255,9 +255,9 @@ static void dumpStructure(const char* name, ExecState* exec, Structure* structur dataLog("%s = %p", name, structure); - size_t offset = structure->get(exec->globalData(), ident); - if (offset != notFound) - dataLog(" (offset = %lu)", static_cast<unsigned long>(offset)); + PropertyOffset offset = structure->get(exec->globalData(), ident); + if (offset != invalidOffset) + dataLog(" (offset = %d)", offset); } #endif diff --git a/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp b/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp index cb3e8e8b6..0df0f44e7 100644 --- a/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp +++ b/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp @@ -50,6 +50,8 @@ GetByIdStatus GetByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned JSCell* specificValue; PropertyOffset offset = structure->get( *profiledBlock->globalData(), ident, attributesIgnored, specificValue); + if (structure->isDictionary()) + specificValue = 0; if (!isValidOffset(offset)) return GetByIdStatus(NoInformation, false); @@ -75,12 +77,13 @@ void GetByIdStatus::computeForChain(GetByIdStatus& result, CodeBlock* profiledBl Structure* currentStructure = structure; JSObject* currentObject = 0; for (unsigned i = 0; i < result.m_chain.size(); ++i) { + ASSERT(!currentStructure->isDictionary()); currentObject = asObject(currentStructure->prototypeForLookup(profiledBlock)); currentStructure = result.m_chain[i]; if (currentObject->structure() != currentStructure) return; } - + ASSERT(currentObject); unsigned attributesIgnored; @@ -88,6 +91,8 @@ void GetByIdStatus::computeForChain(GetByIdStatus& result, CodeBlock* profiledBl result.m_offset = currentStructure->get( *profiledBlock->globalData(), ident, attributesIgnored, specificValue); + if (currentStructure->isDictionary()) + specificValue = 0; if (!isValidOffset(result.m_offset)) return; @@ -155,6 +160,8 @@ GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytec JSCell* specificValue; result.m_offset = structure->get( *profiledBlock->globalData(), ident, attributesIgnored, specificValue); + if (structure->isDictionary()) + specificValue = 0; if (isValidOffset(result.m_offset)) { result.m_structureSet.add(structure); @@ -178,6 +185,8 @@ GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytec JSCell* specificValue; PropertyOffset myOffset = structure->get( *profiledBlock->globalData(), ident, attributesIgnored, specificValue); + if (structure->isDictionary()) + specificValue = 0; if (!isValidOffset(myOffset)) { result.m_offset = invalidOffset; diff --git a/Source/JavaScriptCore/bytecode/GetByIdStatus.h b/Source/JavaScriptCore/bytecode/GetByIdStatus.h index 297ec335f..f38a19e8c 100644 --- a/Source/JavaScriptCore/bytecode/GetByIdStatus.h +++ b/Source/JavaScriptCore/bytecode/GetByIdStatus.h @@ -53,7 +53,7 @@ public: GetByIdStatus( State state, bool wasSeenInJIT, const StructureSet& structureSet = StructureSet(), - size_t offset = invalidOffset, JSValue specificValue = JSValue(), Vector<Structure*> chain = Vector<Structure*>()) + PropertyOffset offset = invalidOffset, JSValue specificValue = JSValue(), Vector<Structure*> chain = Vector<Structure*>()) : m_state(state) , m_structureSet(structureSet) , m_chain(chain) @@ -61,7 +61,7 @@ public: , m_offset(offset) , m_wasSeenInJIT(wasSeenInJIT) { - ASSERT((state == Simple) == (offset != notFound)); + ASSERT((state == Simple) == (offset != invalidOffset)); } static GetByIdStatus computeFor(CodeBlock*, unsigned bytecodeIndex, Identifier&); diff --git a/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.cpp b/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.cpp index 4afee248d..ddc7700c6 100644 --- a/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.cpp +++ b/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.cpp @@ -39,6 +39,8 @@ static ResolveGlobalStatus computeForStructure(CodeBlock* codeBlock, Structure* JSCell* specificValue; PropertyOffset offset = structure->get( *codeBlock->globalData(), identifier, attributesIgnored, specificValue); + if (structure->isDictionary()) + specificValue = 0; if (!isValidOffset(offset)) return ResolveGlobalStatus(); diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp index 9050d590e..94479d6d0 100644 --- a/Source/JavaScriptCore/dfg/DFGOperations.cpp +++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp @@ -1248,7 +1248,7 @@ char* DFG_OPERATION operationAllocatePropertyStorageWithInitialCapacity(ExecStat void* result; if (!globalData.heap.tryAllocateStorage(initialOutOfLineCapacity * sizeof(JSValue), &result)) CRASH(); - return reinterpret_cast<char*>(result); + return reinterpret_cast<char*>(reinterpret_cast<JSValue*>(result) + initialOutOfLineCapacity + 1); } char* DFG_OPERATION operationAllocatePropertyStorage(ExecState* exec, size_t newSize) @@ -1257,7 +1257,7 @@ char* DFG_OPERATION operationAllocatePropertyStorage(ExecState* exec, size_t new void* result; if (!globalData.heap.tryAllocateStorage(newSize, &result)) CRASH(); - return reinterpret_cast<char*>(result); + return reinterpret_cast<char*>(reinterpret_cast<JSValue*>(result) + 1) + newSize; } double DFG_OPERATION operationFModOnInts(int32_t a, int32_t b) diff --git a/Source/JavaScriptCore/dfg/DFGOperations.h b/Source/JavaScriptCore/dfg/DFGOperations.h index d0fbf7ed4..0ff721216 100644 --- a/Source/JavaScriptCore/dfg/DFGOperations.h +++ b/Source/JavaScriptCore/dfg/DFGOperations.h @@ -106,6 +106,7 @@ typedef void DFG_OPERATION (*V_DFGOperation_EPZJ)(ExecState*, void*, int32_t, En typedef void DFG_OPERATION (*V_DFGOperation_W)(WatchpointSet*); typedef char* DFG_OPERATION (*P_DFGOperation_E)(ExecState*); typedef char* DFG_OPERATION (*P_DFGOperation_ES)(ExecState*, size_t); +typedef char* DFG_OPERATION (*P_DFGOperation_EPS)(ExecState*, void*, size_t); // These routines are provide callbacks out to C++ implementations of operations too complex to JIT. JSCell* DFG_OPERATION operationNewObject(ExecState*) WTF_INTERNAL; diff --git a/Source/JavaScriptCore/dfg/DFGRepatch.cpp b/Source/JavaScriptCore/dfg/DFGRepatch.cpp index 19e064f2c..ee0c590a8 100644 --- a/Source/JavaScriptCore/dfg/DFGRepatch.cpp +++ b/Source/JavaScriptCore/dfg/DFGRepatch.cpp @@ -301,7 +301,8 @@ static bool tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier // Optimize self access. if (slot.slotBase() == baseValue) { - if ((slot.cachedPropertyType() != PropertySlot::Value) || ((slot.cachedOffset() * sizeof(JSValue)) > (unsigned)MacroAssembler::MaximumCompactPtrAlignedAddressOffset)) { + if ((slot.cachedPropertyType() != PropertySlot::Value) + || !MacroAssembler::isCompactPtrAlignedAddressOffset(offsetRelativeToPatchedStorage(slot.cachedOffset()))) { dfgRepatchCall(codeBlock, stubInfo.callReturnLocation, operationGetByIdBuildList); return true; } @@ -824,7 +825,7 @@ static void emitPutTransitionStub( stubJit.storePtr(scratchGPR1, &copiedAllocator->m_currentRemaining); stubJit.negPtr(scratchGPR1); stubJit.addPtr(MacroAssembler::AbsoluteAddress(&copiedAllocator->m_currentPayloadEnd), scratchGPR1); - stubJit.subPtr(MacroAssembler::TrustedImm32(newSize), scratchGPR1); + stubJit.addPtr(MacroAssembler::TrustedImm32(sizeof(JSValue)), scratchGPR1); } else { size_t oldSize = oldStructure->outOfLineCapacity() * sizeof(JSValue); ASSERT(newSize > oldSize); @@ -835,11 +836,11 @@ static void emitPutTransitionStub( stubJit.storePtr(scratchGPR1, &copiedAllocator->m_currentRemaining); stubJit.negPtr(scratchGPR1); stubJit.addPtr(MacroAssembler::AbsoluteAddress(&copiedAllocator->m_currentPayloadEnd), scratchGPR1); - stubJit.subPtr(MacroAssembler::TrustedImm32(newSize), scratchGPR1); + stubJit.addPtr(MacroAssembler::TrustedImm32(sizeof(JSValue)), scratchGPR1); // We have scratchGPR1 = new storage, scratchGPR3 = old storage, scratchGPR2 = available - for (size_t offset = 0; offset < oldSize; offset += sizeof(void*)) { - stubJit.loadPtr(MacroAssembler::Address(scratchGPR3, offset), scratchGPR2); - stubJit.storePtr(scratchGPR2, MacroAssembler::Address(scratchGPR1, offset)); + for (ptrdiff_t offset = 0; offset < static_cast<ptrdiff_t>(oldSize); offset += sizeof(void*)) { + stubJit.loadPtr(MacroAssembler::Address(scratchGPR3, -(offset + sizeof(JSValue) * 2)), scratchGPR2); + stubJit.storePtr(scratchGPR2, MacroAssembler::Address(scratchGPR1, -(offset + sizeof(JSValue) * 2))); } } diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp index f368cf298..875ac39f0 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp @@ -1063,7 +1063,7 @@ void SpeculativeJIT::compile(BasicBlock& block) valueSource = ValueSource(DoubleInRegisterFile); else if (isInt32Speculation(argumentPosition.prediction())) valueSource = ValueSource(Int32InRegisterFile); - else if (isArraySpeculation(argumentPosition.prediction())) + else if (isArraySpeculation(argumentPosition.prediction()) || isCellSpeculation(argumentPosition.prediction())) valueSource = ValueSource(CellInRegisterFile); else if (isBooleanSpeculation(argumentPosition.prediction())) valueSource = ValueSource(BooleanInRegisterFile); @@ -3157,7 +3157,7 @@ void SpeculativeJIT::compileAllocatePropertyStorage(Node& node) m_jit.storePtr(scratchGPR, &copiedAllocator->m_currentRemaining); m_jit.negPtr(scratchGPR); m_jit.addPtr(JITCompiler::AbsoluteAddress(&copiedAllocator->m_currentPayloadEnd), scratchGPR); - m_jit.subPtr(JITCompiler::TrustedImm32(newSize), scratchGPR); + m_jit.addPtr(JITCompiler::TrustedImm32(sizeof(JSValue)), scratchGPR); addSlowPathGenerator( slowPathCall(slowPath, this, operationAllocatePropertyStorageWithInitialCapacity, scratchGPR)); @@ -3191,14 +3191,14 @@ void SpeculativeJIT::compileReallocatePropertyStorage(Node& node) m_jit.storePtr(scratchGPR2, &copiedAllocator->m_currentRemaining); m_jit.negPtr(scratchGPR2); m_jit.addPtr(JITCompiler::AbsoluteAddress(&copiedAllocator->m_currentPayloadEnd), scratchGPR2); - m_jit.subPtr(JITCompiler::TrustedImm32(newSize), scratchGPR2); + m_jit.addPtr(JITCompiler::TrustedImm32(sizeof(JSValue)), scratchGPR2); addSlowPathGenerator( slowPathCall(slowPath, this, operationAllocatePropertyStorage, scratchGPR2, newSize)); // We have scratchGPR2 = new storage, scratchGPR1 = scratch - for (size_t offset = 0; offset < oldSize; offset += sizeof(void*)) { - m_jit.loadPtr(JITCompiler::Address(oldStorageGPR, offset), scratchGPR1); - m_jit.storePtr(scratchGPR1, JITCompiler::Address(scratchGPR2, offset)); + for (ptrdiff_t offset = 0; offset < static_cast<ptrdiff_t>(oldSize); offset += sizeof(void*)) { + m_jit.loadPtr(JITCompiler::Address(oldStorageGPR, -(offset + sizeof(JSValue) * 2)), scratchGPR1); + m_jit.storePtr(scratchGPR1, JITCompiler::Address(scratchGPR2, -(offset + sizeof(JSValue) * 2))); } m_jit.storePtr(scratchGPR2, JITCompiler::Address(baseGPR, JSObject::offsetOfOutOfLineStorage())); diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h index cb7d89106..0e412a199 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h @@ -1161,6 +1161,11 @@ public: m_jit.setupArgumentsWithExecState(TrustedImmPtr(size)); return appendCallWithExceptionCheckSetResult(operation, result); } + JITCompiler::Call callOperation(P_DFGOperation_EPS operation, GPRReg result, GPRReg old, size_t size) + { + m_jit.setupArgumentsWithExecState(old, TrustedImmPtr(size)); + return appendCallWithExceptionCheckSetResult(operation, result); + } JITCompiler::Call callOperation(J_DFGOperation_E operation, GPRReg result) { m_jit.setupArgumentsExecState(); diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp index c63ba8c21..6209da485 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp @@ -3913,8 +3913,10 @@ void SpeculativeJIT::compile(Node& node) m_jit.breakpoint(); isOutOfLine.link(&m_jit); #endif - m_jit.load32(JITCompiler::BaseIndex(resultPayloadGPR, resolveInfoGPR, JITCompiler::TimesEight, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag) - inlineStorageCapacity * static_cast<ptrdiff_t>(sizeof(JSValue))), resultTagGPR); - m_jit.load32(JITCompiler::BaseIndex(resultPayloadGPR, resolveInfoGPR, JITCompiler::TimesEight, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload) - inlineStorageCapacity * static_cast<ptrdiff_t>(sizeof(JSValue))), resultPayloadGPR); + m_jit.neg32(resolveInfoGPR); + m_jit.signExtend32ToPtr(resolveInfoGPR, resolveInfoGPR); + m_jit.load32(JITCompiler::BaseIndex(resultPayloadGPR, resolveInfoGPR, JITCompiler::TimesEight, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag) + (inlineStorageCapacity - 2) * static_cast<ptrdiff_t>(sizeof(JSValue))), resultTagGPR); + m_jit.load32(JITCompiler::BaseIndex(resultPayloadGPR, resolveInfoGPR, JITCompiler::TimesEight, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload) + (inlineStorageCapacity - 2) * static_cast<ptrdiff_t>(sizeof(JSValue))), resultPayloadGPR); addSlowPathGenerator( slowPathCall( diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp index 6dbb8a4b1..39f4a0740 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp @@ -3902,8 +3902,10 @@ void SpeculativeJIT::compile(Node& node) m_jit.breakpoint(); isOutOfLine.link(&m_jit); #endif + m_jit.neg32(resolveInfoGPR); + m_jit.signExtend32ToPtr(resolveInfoGPR, resolveInfoGPR); m_jit.loadPtr(JITCompiler::Address(globalObjectGPR, JSObject::offsetOfOutOfLineStorage()), resultGPR); - m_jit.loadPtr(JITCompiler::BaseIndex(resultGPR, resolveInfoGPR, JITCompiler::ScalePtr, -inlineStorageCapacity * static_cast<ptrdiff_t>(sizeof(JSValue))), resultGPR); + m_jit.loadPtr(JITCompiler::BaseIndex(resultGPR, resolveInfoGPR, JITCompiler::ScalePtr, (inlineStorageCapacity - 2) * static_cast<ptrdiff_t>(sizeof(JSValue))), resultGPR); addSlowPathGenerator( slowPathCall( diff --git a/Source/JavaScriptCore/heap/ConservativeRoots.cpp b/Source/JavaScriptCore/heap/ConservativeRoots.cpp index 6b9cbef45..7fe22dfff 100644 --- a/Source/JavaScriptCore/heap/ConservativeRoots.cpp +++ b/Source/JavaScriptCore/heap/ConservativeRoots.cpp @@ -66,10 +66,8 @@ template<typename MarkHook> inline void ConservativeRoots::genericAddPointer(void* p, TinyBloomFilter filter, MarkHook& markHook) { markHook.mark(p); - - CopiedBlock* block; - if (m_copiedSpace->contains(p, block)) - m_copiedSpace->pin(block); + + m_copiedSpace->pinIfNecessary(p); MarkedBlock* candidate = MarkedBlock::blockFor(p); if (filter.ruleOut(reinterpret_cast<Bits>(candidate))) { diff --git a/Source/JavaScriptCore/heap/CopiedSpace.h b/Source/JavaScriptCore/heap/CopiedSpace.h index de682a4c1..be3a331e8 100644 --- a/Source/JavaScriptCore/heap/CopiedSpace.h +++ b/Source/JavaScriptCore/heap/CopiedSpace.h @@ -68,6 +68,8 @@ public: bool contains(CopiedBlock*); bool contains(void*, CopiedBlock*&); + + void pinIfNecessary(void* pointer); size_t size(); size_t capacity(); diff --git a/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h b/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h index f702e1dd9..e2af41ad8 100644 --- a/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h +++ b/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h @@ -57,6 +57,42 @@ inline void CopiedSpace::pin(CopiedBlock* block) block->m_isPinned = true; } +inline void CopiedSpace::pinIfNecessary(void* opaquePointer) +{ + // Pointers into the copied space come in the following varieties: + // 1) Pointers to the start of a span of memory. This is the most + // natural though not necessarily the most common. + // 2) Pointers to one value-sized (8 byte) word past the end of + // a span of memory. This currently occurs with semi-butterflies + // and should be fixed soon, once the other half of the + // butterfly lands. + // 3) Pointers to the innards arising from loop induction variable + // optimizations (either manual ones or automatic, by the + // compiler). + // 4) Pointers to the end of a span of memory in arising from + // induction variable optimizations combined with the + // GC-to-compiler contract laid out in the C spec: a pointer to + // the end of a span of memory must be considered to be a + // pointer to that memory. + + EncodedJSValue* pointer = reinterpret_cast<EncodedJSValue*>(opaquePointer); + CopiedBlock* block; + + // Handle (1) and (3). + if (contains(pointer, block)) + pin(block); + + // Handle (4). We don't have to explicitly check and pin the block under this + // pointer because it cannot possibly point to something that cases (1) and + // (3) above or case (2) below wouldn't already catch. + pointer--; + + // Handle (2) + pointer--; + if (contains(pointer, block)) + pin(block); +} + inline void CopiedSpace::startedCopying() { DoublyLinkedList<HeapBlock>* temp = m_fromSpace; diff --git a/Source/JavaScriptCore/heap/MachineStackMarker.cpp b/Source/JavaScriptCore/heap/MachineStackMarker.cpp index 8e0c57b6a..7eb57479b 100644 --- a/Source/JavaScriptCore/heap/MachineStackMarker.cpp +++ b/Source/JavaScriptCore/heap/MachineStackMarker.cpp @@ -141,8 +141,10 @@ MachineThreads::MachineThreads(Heap* heap) MachineThreads::~MachineThreads() { - if (m_threadSpecific) - ThreadSpecificKeyDelete(m_threadSpecific); + if (m_threadSpecific) { + int error = pthread_key_delete(m_threadSpecific); + ASSERT_UNUSED(error, !error); + } MutexLocker registeredThreadsLock(m_registeredThreadsMutex); for (Thread* t = m_registeredThreads; t;) { @@ -179,17 +181,19 @@ void MachineThreads::makeUsableFromMultipleThreads() if (m_threadSpecific) return; - ThreadSpecificKeyCreate(&m_threadSpecific, removeThread); + int error = pthread_key_create(&m_threadSpecific, removeThread); + if (error) + CRASH(); } void MachineThreads::addCurrentThread() { ASSERT(!m_heap->globalData()->exclusiveThread || m_heap->globalData()->exclusiveThread == currentThread()); - if (!m_threadSpecific || ThreadSpecificGet(m_threadSpecific)) + if (!m_threadSpecific || pthread_getspecific(m_threadSpecific)) return; - ThreadSpecificSet(m_threadSpecific, this); + pthread_setspecific(m_threadSpecific, this); Thread* thread = new Thread(getCurrentPlatformThread(), wtfThreadData().stack().origin()); MutexLocker lock(m_registeredThreadsMutex); diff --git a/Source/JavaScriptCore/heap/MachineStackMarker.h b/Source/JavaScriptCore/heap/MachineStackMarker.h index 3d4aa22d4..5c7705fcf 100644 --- a/Source/JavaScriptCore/heap/MachineStackMarker.h +++ b/Source/JavaScriptCore/heap/MachineStackMarker.h @@ -22,8 +22,8 @@ #ifndef MachineThreads_h #define MachineThreads_h +#include <pthread.h> #include <wtf/Noncopyable.h> -#include <wtf/ThreadSpecific.h> #include <wtf/ThreadingPrimitives.h> namespace JSC { @@ -55,7 +55,7 @@ namespace JSC { Heap* m_heap; Mutex m_registeredThreadsMutex; Thread* m_registeredThreads; - WTF::ThreadSpecificKey m_threadSpecific; + pthread_key_t m_threadSpecific; }; } // namespace JSC diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp index 466cff7db..86078fbc3 100644 --- a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp +++ b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp @@ -159,9 +159,10 @@ void JIT::compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID if (finalObjectMode == MayBeFinal) { Jump isInline = branch32(LessThan, offset, TrustedImm32(inlineStorageCapacity)); loadPtr(Address(base, JSObject::offsetOfOutOfLineStorage()), scratch); + neg32(offset); Jump done = jump(); isInline.link(this); - addPtr(TrustedImm32(JSObject::offsetOfInlineStorage() + inlineStorageCapacity * sizeof(EncodedJSValue)), base, scratch); + addPtr(TrustedImm32(JSObject::offsetOfInlineStorage() - (inlineStorageCapacity - 2) * sizeof(EncodedJSValue)), base, scratch); done.link(this); } else { #if !ASSERT_DISABLED @@ -170,8 +171,10 @@ void JIT::compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID isOutOfLine.link(this); #endif loadPtr(Address(base, JSObject::offsetOfOutOfLineStorage()), scratch); + neg32(offset); } - loadPtr(BaseIndex(scratch, offset, ScalePtr, -inlineStorageCapacity * static_cast<ptrdiff_t>(sizeof(JSValue))), result); + signExtend32ToPtr(offset, offset); + loadPtr(BaseIndex(scratch, offset, ScalePtr, (inlineStorageCapacity - 2) * static_cast<ptrdiff_t>(sizeof(JSValue))), result); } void JIT::emit_op_get_by_pname(Instruction* currentInstruction) diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp index 84996d9f0..365ecd20a 100644 --- a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp +++ b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp @@ -1018,9 +1018,10 @@ void JIT::compileGetDirectOffset(RegisterID base, RegisterID resultTag, Register if (finalObjectMode == MayBeFinal) { Jump isInline = branch32(LessThan, offset, TrustedImm32(inlineStorageCapacity)); loadPtr(Address(base, JSObject::offsetOfOutOfLineStorage()), base); + neg32(offset); Jump done = jump(); isInline.link(this); - addPtr(TrustedImmPtr(JSObject::offsetOfInlineStorage() + inlineStorageCapacity * sizeof(EncodedJSValue)), base); + addPtr(TrustedImmPtr(JSObject::offsetOfInlineStorage() - (inlineStorageCapacity - 2) * sizeof(EncodedJSValue)), base); done.link(this); } else { #if !ASSERT_DISABLED @@ -1029,9 +1030,10 @@ void JIT::compileGetDirectOffset(RegisterID base, RegisterID resultTag, Register isOutOfLine.link(this); #endif loadPtr(Address(base, JSObject::offsetOfOutOfLineStorage()), base); + neg32(offset); } - load32(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload) - inlineStorageCapacity * sizeof(EncodedJSValue)), resultPayload); - load32(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag) - inlineStorageCapacity * 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) diff --git a/Source/JavaScriptCore/jit/JITStubs.cpp b/Source/JavaScriptCore/jit/JITStubs.cpp index bfc4709bc..0f03a0a4a 100644 --- a/Source/JavaScriptCore/jit/JITStubs.cpp +++ b/Source/JavaScriptCore/jit/JITStubs.cpp @@ -932,7 +932,8 @@ NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* co if (slot.slotBase() == baseValue) { // set this up, so derefStructures can do it's job. stubInfo->initGetByIdSelf(callFrame->globalData(), codeBlock->ownerExecutable(), structure); - if ((slot.cachedPropertyType() != PropertySlot::Value) || ((slot.cachedOffset() * sizeof(JSValue)) > (unsigned)MacroAssembler::MaximumCompactPtrAlignedAddressOffset)) + if ((slot.cachedPropertyType() != PropertySlot::Value) + || !MacroAssembler::isCompactPtrAlignedAddressOffset(offsetRelativeToPatchedStorage(slot.cachedOffset()))) ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_self_fail)); else JIT::patchGetByIdSelf(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress); diff --git a/Source/JavaScriptCore/jsc.cpp b/Source/JavaScriptCore/jsc.cpp index 00ad5d3b2..17ab51588 100644 --- a/Source/JavaScriptCore/jsc.cpp +++ b/Source/JavaScriptCore/jsc.cpp @@ -84,6 +84,7 @@ static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState*); static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState*); static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*); static EncodedJSValue JSC_HOST_CALL functionGC(ExecState*); #ifndef NDEBUG @@ -191,6 +192,7 @@ protected: Base::finishCreation(globalData); addFunction(globalData, "debug", functionDebug, 1); + addFunction(globalData, "describe", functionDescribe, 1); addFunction(globalData, "print", functionPrint, 1); addFunction(globalData, "quit", functionQuit, 0); addFunction(globalData, "gc", functionGC, 0); @@ -298,6 +300,12 @@ EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec) return JSValue::encode(jsUndefined()); } +EncodedJSValue JSC_HOST_CALL functionDescribe(ExecState* exec) +{ + fprintf(stderr, "--> %s\n", exec->argument(0).description()); + return JSValue::encode(jsUndefined()); +} + EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState* exec) { String trace = "--> Stack trace:\n"; diff --git a/Source/JavaScriptCore/llint/LLIntCommon.h b/Source/JavaScriptCore/llint/LLIntCommon.h index 6b908eae2..1797ff02e 100644 --- a/Source/JavaScriptCore/llint/LLIntCommon.h +++ b/Source/JavaScriptCore/llint/LLIntCommon.h @@ -36,6 +36,9 @@ // how the GC allocates. #define LLINT_ALWAYS_ALLOCATE_SLOW 0 +// Disable inline caching of get_by_id and put_by_id. +#define LLINT_ALWAYS_ACCESS_SLOW 0 + // Enable OSR into the JIT. Disabling this while the LLInt is enabled effectively // turns off all JIT'ing, since in LLInt's parlance, OSR subsumes any form of JIT // invocation. diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp index fbc0146b8..d2d743e0a 100644 --- a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp +++ b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp @@ -883,7 +883,8 @@ LLINT_SLOW_PATH_DECL(slow_path_get_by_id) LLINT_CHECK_EXCEPTION(); LLINT_OP(1) = result; - if (baseValue.isCell() + if (!LLINT_ALWAYS_ACCESS_SLOW + && baseValue.isCell() && slot.isCacheable() && slot.slotBase() == baseValue && slot.cachedPropertyType() == PropertySlot::Value) { @@ -935,7 +936,8 @@ LLINT_SLOW_PATH_DECL(slow_path_put_by_id) baseValue.put(exec, ident, LLINT_OP_C(3).jsValue(), slot); LLINT_CHECK_EXCEPTION(); - if (baseValue.isCell() + if (!LLINT_ALWAYS_ACCESS_SLOW + && baseValue.isCell() && slot.isCacheable()) { JSCell* baseCell = baseValue.asCell(); diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm index 513b742ee..b8115dd6b 100644 --- a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm +++ b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm @@ -921,20 +921,22 @@ _llint_op_is_string: macro loadPropertyAtVariableOffsetKnownNotFinal(propertyOffset, objectAndStorage, tag, payload) assert(macro (ok) bigteq propertyOffset, InlineStorageCapacity, ok end) + negi propertyOffset loadp JSObject::m_outOfLineStorage[objectAndStorage], objectAndStorage - loadi TagOffset - 8 * InlineStorageCapacity[objectAndStorage, propertyOffset, 8], tag - loadi PayloadOffset - 8 * InlineStorageCapacity[objectAndStorage, propertyOffset, 8], payload + loadi TagOffset + (InlineStorageCapacity - 2) * 8[objectAndStorage, propertyOffset, 8], tag + loadi PayloadOffset + (InlineStorageCapacity - 2) * 8[objectAndStorage, propertyOffset, 8], payload end macro loadPropertyAtVariableOffset(propertyOffset, objectAndStorage, tag, payload) bilt propertyOffset, InlineStorageCapacity, .isInline loadp JSObject::m_outOfLineStorage[objectAndStorage], objectAndStorage + negi propertyOffset jmp .ready .isInline: - addp JSFinalObject::m_inlineStorage + InlineStorageCapacity * 8, objectAndStorage + addp JSFinalObject::m_inlineStorage - (InlineStorageCapacity - 2) * 8, objectAndStorage .ready: - loadi TagOffset - 8 * InlineStorageCapacity[objectAndStorage, propertyOffset, 8], tag - loadi PayloadOffset - 8 * InlineStorageCapacity[objectAndStorage, propertyOffset, 8], payload + loadi TagOffset + (InlineStorageCapacity - 2) * 8[objectAndStorage, propertyOffset, 8], tag + loadi PayloadOffset + (InlineStorageCapacity - 2) * 8[objectAndStorage, propertyOffset, 8], payload end macro resolveGlobal(size, slow) diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm index b976421f0..6e752a6d0 100644 --- a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm +++ b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm @@ -778,20 +778,23 @@ _llint_op_is_string: dispatch(3) -macro loadPropertyAtVariableOffsetKnownNotFinal(propertyOffset, objectAndStorage, value) - assert(macro (ok) bigteq propertyOffset, InlineStorageCapacity, ok end) +macro loadPropertyAtVariableOffsetKnownNotFinal(propertyOffsetAsPointer, objectAndStorage, value) + assert(macro (ok) bigteq propertyOffsetAsPointer, InlineStorageCapacity, ok end) + negp propertyOffsetAsPointer loadp JSObject::m_outOfLineStorage[objectAndStorage], objectAndStorage - loadp -8 * InlineStorageCapacity[objectAndStorage, propertyOffset, 8], value + loadp (InlineStorageCapacity - 2) * 8[objectAndStorage, propertyOffsetAsPointer, 8], value end -macro loadPropertyAtVariableOffset(propertyOffset, objectAndStorage, value) - bilt propertyOffset, InlineStorageCapacity, .isInline +macro loadPropertyAtVariableOffset(propertyOffsetAsInt, objectAndStorage, value) + bilt propertyOffsetAsInt, InlineStorageCapacity, .isInline loadp JSObject::m_outOfLineStorage[objectAndStorage], objectAndStorage + negi propertyOffsetAsInt + sxi2p propertyOffsetAsInt, propertyOffsetAsInt jmp .ready .isInline: - addp JSFinalObject::m_inlineStorage + InlineStorageCapacity * 8, objectAndStorage + addp JSFinalObject::m_inlineStorage - (InlineStorageCapacity - 2) * 8, objectAndStorage .ready: - loadp -8 * InlineStorageCapacity[objectAndStorage, propertyOffset, 8], value + loadp (InlineStorageCapacity - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8], value end macro resolveGlobal(size, slow) diff --git a/Source/JavaScriptCore/runtime/DateConstructor.cpp b/Source/JavaScriptCore/runtime/DateConstructor.cpp index 08b815035..0325080f6 100644 --- a/Source/JavaScriptCore/runtime/DateConstructor.cpp +++ b/Source/JavaScriptCore/runtime/DateConstructor.cpp @@ -136,13 +136,13 @@ JSObject* constructDate(ExecState* exec, JSGlobalObject* globalObject, const Arg else { GregorianDateTime t; int year = JSC::toInt32(doubleArguments[0]); - t.year = (year >= 0 && year <= 99) ? year : year - 1900; - t.month = JSC::toInt32(doubleArguments[1]); - t.monthDay = (numArgs >= 3) ? JSC::toInt32(doubleArguments[2]) : 1; - t.hour = JSC::toInt32(doubleArguments[3]); - t.minute = JSC::toInt32(doubleArguments[4]); - t.second = JSC::toInt32(doubleArguments[5]); - t.isDST = -1; + t.setYear((year >= 0 && year <= 99) ? year : year - 1900); + t.setMonth(JSC::toInt32(doubleArguments[1])); + t.setMonthDay((numArgs >= 3) ? JSC::toInt32(doubleArguments[2]) : 1); + t.setHour(JSC::toInt32(doubleArguments[3])); + t.setMinute(JSC::toInt32(doubleArguments[4])); + t.setSecond(JSC::toInt32(doubleArguments[5])); + t.setIsDST(-1); double ms = (numArgs >= 7) ? doubleArguments[6] : 0; value = gregorianDateTimeToMS(exec, t, ms, false); } @@ -214,12 +214,12 @@ static EncodedJSValue JSC_HOST_CALL dateUTC(ExecState* exec) GregorianDateTime t; int year = JSC::toInt32(doubleArguments[0]); - t.year = (year >= 0 && year <= 99) ? year : year - 1900; - t.month = JSC::toInt32(doubleArguments[1]); - t.monthDay = (n >= 3) ? JSC::toInt32(doubleArguments[2]) : 1; - t.hour = JSC::toInt32(doubleArguments[3]); - t.minute = JSC::toInt32(doubleArguments[4]); - t.second = JSC::toInt32(doubleArguments[5]); + t.setYear((year >= 0 && year <= 99) ? year : year - 1900); + t.setMonth(JSC::toInt32(doubleArguments[1])); + t.setMonthDay((n >= 3) ? JSC::toInt32(doubleArguments[2]) : 1); + t.setHour(JSC::toInt32(doubleArguments[3])); + t.setMinute(JSC::toInt32(doubleArguments[4])); + t.setSecond(JSC::toInt32(doubleArguments[5])); double ms = (n >= 7) ? doubleArguments[6] : 0; return JSValue::encode(jsNumber(timeClip(gregorianDateTimeToMS(exec, t, ms, true)))); } diff --git a/Source/JavaScriptCore/runtime/DateConversion.cpp b/Source/JavaScriptCore/runtime/DateConversion.cpp index 7bc0cbc0f..e8714c14c 100644 --- a/Source/JavaScriptCore/runtime/DateConversion.cpp +++ b/Source/JavaScriptCore/runtime/DateConversion.cpp @@ -55,53 +55,41 @@ using namespace WTF; namespace JSC { -double parseDate(ExecState* exec, const UString &date) -{ - if (date == exec->globalData().cachedDateString) - return exec->globalData().cachedDateStringValue; - double value = parseES5DateFromNullTerminatedCharacters(date.utf8().data()); - if (isnan(value)) - value = parseDateFromNullTerminatedCharacters(exec, date.utf8().data()); - exec->globalData().cachedDateString = date; - exec->globalData().cachedDateStringValue = value; - return value; -} - void formatDate(const GregorianDateTime &t, DateConversionBuffer& buffer) { snprintf(buffer, DateConversionBufferSize, "%s %s %02d %04d", - weekdayName[(t.weekDay + 6) % 7], - monthName[t.month], t.monthDay, t.year + 1900); + weekdayName[(t.weekDay() + 6) % 7], + monthName[t.month()], t.monthDay(), t.year() + 1900); } void formatDateUTCVariant(const GregorianDateTime &t, DateConversionBuffer& buffer) { snprintf(buffer, DateConversionBufferSize, "%s, %02d %s %04d", - weekdayName[(t.weekDay + 6) % 7], - t.monthDay, monthName[t.month], t.year + 1900); + weekdayName[(t.weekDay() + 6) % 7], + t.monthDay(), monthName[t.month()], t.year() + 1900); } void formatTime(const GregorianDateTime &t, DateConversionBuffer& buffer) { - int offset = abs(gmtoffset(t)); + int offset = abs(t.utcOffset()); char timeZoneName[70]; struct tm gtm = t; strftime(timeZoneName, sizeof(timeZoneName), "%Z", >m); if (timeZoneName[0]) { snprintf(buffer, DateConversionBufferSize, "%02d:%02d:%02d GMT%c%02d%02d (%s)", - t.hour, t.minute, t.second, - gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60, timeZoneName); + t.hour(), t.minute(), t.second(), + t.utcOffset() < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60, timeZoneName); } else { snprintf(buffer, DateConversionBufferSize, "%02d:%02d:%02d GMT%c%02d%02d", - t.hour, t.minute, t.second, - gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60); + t.hour(), t.minute(), t.second(), + t.utcOffset() < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60); } } void formatTimeUTC(const GregorianDateTime &t, DateConversionBuffer& buffer) { - snprintf(buffer, DateConversionBufferSize, "%02d:%02d:%02d GMT", t.hour, t.minute, t.second); + snprintf(buffer, DateConversionBufferSize, "%02d:%02d:%02d GMT", t.hour(), t.minute(), t.second()); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/DateConversion.h b/Source/JavaScriptCore/runtime/DateConversion.h index ff32b503d..0b078cd34 100644 --- a/Source/JavaScriptCore/runtime/DateConversion.h +++ b/Source/JavaScriptCore/runtime/DateConversion.h @@ -42,17 +42,15 @@ #ifndef DateConversion_h #define DateConversion_h -#include "UString.h" +#include <wtf/GregorianDateTime.h> namespace JSC { class ExecState; -struct GregorianDateTime; static const unsigned DateConversionBufferSize = 100; typedef char DateConversionBuffer[DateConversionBufferSize]; -double parseDate(ExecState* exec, const UString&); void formatDate(const GregorianDateTime&, DateConversionBuffer&); void formatDateUTCVariant(const GregorianDateTime&, DateConversionBuffer&); void formatTime(const GregorianDateTime&, DateConversionBuffer&); diff --git a/Source/JavaScriptCore/runtime/DateInstance.h b/Source/JavaScriptCore/runtime/DateInstance.h index 7c976a514..9742e6889 100644 --- a/Source/JavaScriptCore/runtime/DateInstance.h +++ b/Source/JavaScriptCore/runtime/DateInstance.h @@ -23,10 +23,6 @@ #include "JSWrapperObject.h" -namespace WTF { - struct GregorianDateTime; -} - namespace JSC { class DateInstance : public JSWrapperObject { diff --git a/Source/JavaScriptCore/runtime/DatePrototype.cpp b/Source/JavaScriptCore/runtime/DatePrototype.cpp index d3d0fe574..aa65acd05 100644 --- a/Source/JavaScriptCore/runtime/DatePrototype.cpp +++ b/Source/JavaScriptCore/runtime/DatePrototype.cpp @@ -222,13 +222,13 @@ static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, L #if OS(WINDOWS) SYSTEMTIME systemTime; memset(&systemTime, 0, sizeof(systemTime)); - systemTime.wYear = gdt.year + 1900; - systemTime.wMonth = gdt.month + 1; - systemTime.wDay = gdt.monthDay; - systemTime.wDayOfWeek = gdt.weekDay; - systemTime.wHour = gdt.hour; - systemTime.wMinute = gdt.minute; - systemTime.wSecond = gdt.second; + systemTime.wYear = gdt.year() + 1900; + systemTime.wMonth = gdt.month() + 1; + systemTime.wDay = gdt.monthDay(); + systemTime.wDayOfWeek = gdt.weekDay(); + systemTime.wHour = gdt.hour(); + systemTime.wMinute = gdt.minute(); + systemTime.wSecond = gdt.second(); Vector<UChar, 128> buffer; size_t length = 0; @@ -265,7 +265,7 @@ static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, L // Offset year if needed struct tm localTM = gdt; - int year = gdt.year + 1900; + int year = gdt.year() + 1900; bool yearNeedsOffset = year < 1900 || year > 2038; if (yearNeedsOffset) localTM.tm_year = equivalentYearForDST(year) - 1900; @@ -357,7 +357,7 @@ static bool fillStructuresUsingTimeArgs(ExecState* exec, int maxArgs, double* ms // hours if (maxArgs >= 4 && idx < numArgs) { - t->hour = 0; + t->setHour(0); double hours = exec->argument(idx++).toIntegerPreserveNaN(exec); ok = isfinite(hours); milliseconds += hours * msPerHour; @@ -365,7 +365,7 @@ static bool fillStructuresUsingTimeArgs(ExecState* exec, int maxArgs, double* ms // minutes if (maxArgs >= 3 && idx < numArgs && ok) { - t->minute = 0; + t->setMinute(0); double minutes = exec->argument(idx++).toIntegerPreserveNaN(exec); ok = isfinite(minutes); milliseconds += minutes * msPerMinute; @@ -373,7 +373,7 @@ static bool fillStructuresUsingTimeArgs(ExecState* exec, int maxArgs, double* ms // seconds if (maxArgs >= 2 && idx < numArgs && ok) { - t->second = 0; + t->setSecond(0); double seconds = exec->argument(idx++).toIntegerPreserveNaN(exec); ok = isfinite(seconds); milliseconds += seconds * msPerSecond; @@ -412,19 +412,19 @@ static bool fillStructuresUsingDateArgs(ExecState *exec, int maxArgs, double *ms if (maxArgs >= 3 && idx < numArgs) { double years = exec->argument(idx++).toIntegerPreserveNaN(exec); ok = isfinite(years); - t->year = toInt32(years - 1900); + t->setYear(toInt32(years - 1900)); } // months if (maxArgs >= 2 && idx < numArgs && ok) { double months = exec->argument(idx++).toIntegerPreserveNaN(exec); ok = isfinite(months); - t->month = toInt32(months); + t->setMonth(toInt32(months)); } // days if (idx < numArgs && ok) { double days = exec->argument(idx++).toIntegerPreserveNaN(exec); ok = isfinite(days); - t->monthDay = 0; + t->setMonthDay(0); *ms += days * msPerDay; } @@ -567,10 +567,10 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec) int ms = static_cast<int>(fmod(thisDateObj->internalNumber(), msPerSecond)); if (ms < 0) ms += msPerSecond; - if (gregorianDateTime->year > 8099 || gregorianDateTime->year < -1900) - snprintf(buffer, sizeof(buffer) - 1, "%+07d-%02d-%02dT%02d:%02d:%02d.%03dZ", 1900 + gregorianDateTime->year, gregorianDateTime->month + 1, gregorianDateTime->monthDay, gregorianDateTime->hour, gregorianDateTime->minute, gregorianDateTime->second, ms); + if (gregorianDateTime->year() > 8099 || gregorianDateTime->year() < -1900) + snprintf(buffer, sizeof(buffer) - 1, "%+07d-%02d-%02dT%02d:%02d:%02d.%03dZ", 1900 + gregorianDateTime->year(), gregorianDateTime->month() + 1, gregorianDateTime->monthDay(), gregorianDateTime->hour(), gregorianDateTime->minute(), gregorianDateTime->second(), ms); else - snprintf(buffer, sizeof(buffer) - 1, "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", 1900 + gregorianDateTime->year, gregorianDateTime->month + 1, gregorianDateTime->monthDay, gregorianDateTime->hour, gregorianDateTime->minute, gregorianDateTime->second, ms); + snprintf(buffer, sizeof(buffer) - 1, "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", 1900 + gregorianDateTime->year(), gregorianDateTime->month() + 1, gregorianDateTime->monthDay(), gregorianDateTime->hour(), gregorianDateTime->minute(), gregorianDateTime->second(), ms); buffer[sizeof(buffer) - 1] = 0; return JSValue::encode(jsNontrivialString(exec, buffer)); } @@ -657,7 +657,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState* exec) const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec); if (!gregorianDateTime) return JSValue::encode(jsNaN()); - return JSValue::encode(jsNumber(1900 + gregorianDateTime->year)); + return JSValue::encode(jsNumber(1900 + gregorianDateTime->year())); } EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState* exec) @@ -671,7 +671,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState* exec) const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec); if (!gregorianDateTime) return JSValue::encode(jsNaN()); - return JSValue::encode(jsNumber(1900 + gregorianDateTime->year)); + return JSValue::encode(jsNumber(1900 + gregorianDateTime->year())); } EncodedJSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState* exec) @@ -703,7 +703,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec) const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec); if (!gregorianDateTime) return JSValue::encode(jsNaN()); - return JSValue::encode(jsNumber(gregorianDateTime->month)); + return JSValue::encode(jsNumber(gregorianDateTime->month())); } EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState* exec) @@ -717,7 +717,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState* exec) const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec); if (!gregorianDateTime) return JSValue::encode(jsNaN()); - return JSValue::encode(jsNumber(gregorianDateTime->month)); + return JSValue::encode(jsNumber(gregorianDateTime->month())); } EncodedJSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState* exec) @@ -731,7 +731,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState* exec) const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec); if (!gregorianDateTime) return JSValue::encode(jsNaN()); - return JSValue::encode(jsNumber(gregorianDateTime->monthDay)); + return JSValue::encode(jsNumber(gregorianDateTime->monthDay())); } EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState* exec) @@ -745,7 +745,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState* exec) const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec); if (!gregorianDateTime) return JSValue::encode(jsNaN()); - return JSValue::encode(jsNumber(gregorianDateTime->monthDay)); + return JSValue::encode(jsNumber(gregorianDateTime->monthDay())); } EncodedJSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState* exec) @@ -759,7 +759,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState* exec) const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec); if (!gregorianDateTime) return JSValue::encode(jsNaN()); - return JSValue::encode(jsNumber(gregorianDateTime->weekDay)); + return JSValue::encode(jsNumber(gregorianDateTime->weekDay())); } EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState* exec) @@ -773,7 +773,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState* exec) const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec); if (!gregorianDateTime) return JSValue::encode(jsNaN()); - return JSValue::encode(jsNumber(gregorianDateTime->weekDay)); + return JSValue::encode(jsNumber(gregorianDateTime->weekDay())); } EncodedJSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState* exec) @@ -787,7 +787,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState* exec) const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec); if (!gregorianDateTime) return JSValue::encode(jsNaN()); - return JSValue::encode(jsNumber(gregorianDateTime->hour)); + return JSValue::encode(jsNumber(gregorianDateTime->hour())); } EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState* exec) @@ -801,7 +801,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState* exec) const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec); if (!gregorianDateTime) return JSValue::encode(jsNaN()); - return JSValue::encode(jsNumber(gregorianDateTime->hour)); + return JSValue::encode(jsNumber(gregorianDateTime->hour())); } EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState* exec) @@ -815,7 +815,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState* exec) const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec); if (!gregorianDateTime) return JSValue::encode(jsNaN()); - return JSValue::encode(jsNumber(gregorianDateTime->minute)); + return JSValue::encode(jsNumber(gregorianDateTime->minute())); } EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState* exec) @@ -829,7 +829,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState* exec) const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec); if (!gregorianDateTime) return JSValue::encode(jsNaN()); - return JSValue::encode(jsNumber(gregorianDateTime->minute)); + return JSValue::encode(jsNumber(gregorianDateTime->minute())); } EncodedJSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState* exec) @@ -843,7 +843,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState* exec) const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec); if (!gregorianDateTime) return JSValue::encode(jsNaN()); - return JSValue::encode(jsNumber(gregorianDateTime->second)); + return JSValue::encode(jsNumber(gregorianDateTime->second())); } EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState* exec) @@ -857,7 +857,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState* exec) const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec); if (!gregorianDateTime) return JSValue::encode(jsNaN()); - return JSValue::encode(jsNumber(gregorianDateTime->second)); + return JSValue::encode(jsNumber(gregorianDateTime->second())); } EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState* exec) @@ -903,7 +903,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState* exec) const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec); if (!gregorianDateTime) return JSValue::encode(jsNaN()); - return JSValue::encode(jsNumber(-gregorianDateTime->utcOffset / minutesPerHour)); + return JSValue::encode(jsNumber(-gregorianDateTime->utcOffset() / minutesPerHour)); } EncodedJSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState* exec) @@ -1087,36 +1087,36 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec) if (!thisValue.inherits(&DateInstance::s_info)) return throwVMTypeError(exec); - DateInstance* thisDateObj = asDateInstance(thisValue); + DateInstance* thisDateObj = asDateInstance(thisValue); if (!exec->argumentCount()) { JSValue result = jsNaN(); thisDateObj->setInternalValue(exec->globalData(), result); return JSValue::encode(result); } - + double milli = thisDateObj->internalNumber(); double ms = 0; GregorianDateTime gregorianDateTime; if (isnan(milli)) // Based on ECMA 262 B.2.5 (setYear) - // the time must be reset to +0 if it is NaN. + // the time must be reset to +0 if it is NaN. msToGregorianDateTime(exec, 0, true, gregorianDateTime); - else { + else { double secs = floor(milli / msPerSecond); ms = milli - secs * msPerSecond; if (const GregorianDateTime* other = thisDateObj->gregorianDateTime(exec)) gregorianDateTime.copyFrom(*other); } - + double year = exec->argument(0).toIntegerPreserveNaN(exec); if (!isfinite(year)) { JSValue result = jsNaN(); thisDateObj->setInternalValue(exec->globalData(), result); return JSValue::encode(result); } - - gregorianDateTime.year = toInt32((year > 99 || year < 0) ? year - 1900 : year); + + gregorianDateTime.setYear(toInt32((year > 99 || year < 0) ? year - 1900 : year)); JSValue result = jsNumber(gregorianDateTimeToMS(exec, gregorianDateTime, ms, false)); thisDateObj->setInternalValue(exec->globalData(), result); return JSValue::encode(result); @@ -1135,7 +1135,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState* exec) return JSValue::encode(jsNaN()); // NOTE: IE returns the full year even in getYear. - return JSValue::encode(jsNumber(gregorianDateTime->year)); + return JSValue::encode(jsNumber(gregorianDateTime->year())); } EncodedJSValue JSC_HOST_CALL dateProtoFuncToJSON(ExecState* exec) diff --git a/Source/JavaScriptCore/runtime/GCActivityCallbackBlackBerry.cpp b/Source/JavaScriptCore/runtime/GCActivityCallbackBlackBerry.cpp index d9f96fa1e..c052c61ba 100644 --- a/Source/JavaScriptCore/runtime/GCActivityCallbackBlackBerry.cpp +++ b/Source/JavaScriptCore/runtime/GCActivityCallbackBlackBerry.cpp @@ -34,6 +34,7 @@ DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap) void DefaultGCActivityCallback::doWork() { + JSLock lock(SilenceAssertionsOnly); m_globalData->heap.collect(Heap::DoNotSweep); } diff --git a/Source/JavaScriptCore/runtime/JSDateMath.cpp b/Source/JavaScriptCore/runtime/JSDateMath.cpp index dbe748835..a7840938c 100644 --- a/Source/JavaScriptCore/runtime/JSDateMath.cpp +++ b/Source/JavaScriptCore/runtime/JSDateMath.cpp @@ -203,8 +203,8 @@ double getUTCOffset(ExecState* exec) double gregorianDateTimeToMS(ExecState* exec, const GregorianDateTime& t, double milliSeconds, bool inputIsUTC) { - double day = dateToDaysFrom1970(t.year + 1900, t.month, t.monthDay); - double ms = timeToMS(t.hour, t.minute, t.second, milliSeconds); + double day = dateToDaysFrom1970(t.year() + 1900, t.month(), t.monthDay()); + double ms = timeToMS(t.hour(), t.minute(), t.second(), milliSeconds); double result = (day * WTF::msPerDay) + ms; if (!inputIsUTC) { // convert to UTC @@ -228,17 +228,16 @@ void msToGregorianDateTime(ExecState* exec, double ms, bool outputIsUTC, Gregori } const int year = msToYear(ms); - tm.second = msToSeconds(ms); - tm.minute = msToMinutes(ms); - tm.hour = msToHours(ms); - tm.weekDay = msToWeekDay(ms); - tm.yearDay = dayInYear(ms, year); - tm.monthDay = dayInMonthFromDayInYear(tm.yearDay, isLeapYear(year)); - tm.month = monthFromDayInYear(tm.yearDay, isLeapYear(year)); - tm.year = year - 1900; - tm.isDST = dstOff != 0.0; - tm.utcOffset = static_cast<long>((dstOff + utcOff) / WTF::msPerSecond); - tm.timeZone = nullptr; + tm.setSecond(msToSeconds(ms)); + tm.setMinute(msToMinutes(ms)); + tm.setHour(msToHours(ms)); + tm.setWeekDay(msToWeekDay(ms)); + tm.setYearDay(dayInYear(ms, year)); + tm.setMonthDay(dayInMonthFromDayInYear(tm.yearDay(), isLeapYear(year))); + tm.setMonth(monthFromDayInYear(tm.yearDay(), isLeapYear(year))); + tm.setYear(year - 1900); + tm.setIsDST(dstOff != 0.0); + tm.setUtcOffset(static_cast<long>((dstOff + utcOff) / WTF::msPerSecond)); } double parseDateFromNullTerminatedCharacters(ExecState* exec, const char* dateString) @@ -259,4 +258,16 @@ double parseDateFromNullTerminatedCharacters(ExecState* exec, const char* dateSt return ms - (offset * WTF::msPerMinute); } +double parseDate(ExecState* exec, const UString& date) +{ + if (date == exec->globalData().cachedDateString) + return exec->globalData().cachedDateStringValue; + double value = parseES5DateFromNullTerminatedCharacters(date.utf8().data()); + if (isnan(value)) + value = parseDateFromNullTerminatedCharacters(exec, date.utf8().data()); + exec->globalData().cachedDateString = date; + exec->globalData().cachedDateStringValue = value; + return value; +} + } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSDateMath.h b/Source/JavaScriptCore/runtime/JSDateMath.h index f77cf1e75..c7fb5a975 100644 --- a/Source/JavaScriptCore/runtime/JSDateMath.h +++ b/Source/JavaScriptCore/runtime/JSDateMath.h @@ -44,98 +44,18 @@ #define JSDateMath_h #include <wtf/DateMath.h> +#include <wtf/GregorianDateTime.h> namespace JSC { class ExecState; -struct GregorianDateTime; +class UString; void msToGregorianDateTime(ExecState*, double, bool outputIsUTC, GregorianDateTime&); double gregorianDateTimeToMS(ExecState*, const GregorianDateTime&, double, bool inputIsUTC); double getUTCOffset(ExecState*); double parseDateFromNullTerminatedCharacters(ExecState*, const char* dateString); - -// Intentionally overridding the default tm of the system. -// The members of tm differ on various operating systems. -struct GregorianDateTime { - WTF_MAKE_NONCOPYABLE(GregorianDateTime); -public: - GregorianDateTime() - : second(0) - , minute(0) - , hour(0) - , weekDay(0) - , monthDay(0) - , yearDay(0) - , month(0) - , year(0) - , isDST(0) - , utcOffset(0) - { - } - - operator tm() const - { - tm ret; - memset(&ret, 0, sizeof(ret)); - - ret.tm_sec = second; - ret.tm_min = minute; - ret.tm_hour = hour; - ret.tm_wday = weekDay; - ret.tm_mday = monthDay; - ret.tm_yday = yearDay; - ret.tm_mon = month; - ret.tm_year = year; - ret.tm_isdst = isDST; - -#if HAVE(TM_GMTOFF) - ret.tm_gmtoff = static_cast<long>(utcOffset); -#endif -#if HAVE(TM_ZONE) - ret.tm_zone = timeZone.get(); -#endif - - return ret; - } - - void copyFrom(const GregorianDateTime& rhs) - { - second = rhs.second; - minute = rhs.minute; - hour = rhs.hour; - weekDay = rhs.weekDay; - monthDay = rhs.monthDay; - yearDay = rhs.yearDay; - month = rhs.month; - year = rhs.year; - isDST = rhs.isDST; - utcOffset = rhs.utcOffset; - if (rhs.timeZone) { - int inZoneSize = strlen(rhs.timeZone.get()) + 1; - timeZone = adoptArrayPtr(new char[inZoneSize]); - strncpy(timeZone.get(), rhs.timeZone.get(), inZoneSize); - } else - timeZone = nullptr; - } - - int second; - int minute; - int hour; - int weekDay; - int monthDay; - int yearDay; - int month; - int year; - int isDST; - int utcOffset; - OwnArrayPtr<char> timeZone; -}; - -static inline int gmtoffset(const GregorianDateTime& t) -{ - return t.utcOffset; -} +double parseDate(ExecState*, const UString&); } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp index 587929f66..a84597f8b 100644 --- a/Source/JavaScriptCore/runtime/JSObject.cpp +++ b/Source/JavaScriptCore/runtime/JSObject.cpp @@ -99,10 +99,11 @@ void JSObject::visitChildren(JSCell* cell, SlotVisitor& visitor) PropertyStorage storage = thisObject->outOfLineStorage(); if (storage) { size_t storageSize = thisObject->structure()->outOfLineSizeForKnownNonFinalObject(); + size_t capacity = thisObject->structure()->outOfLineCapacity(); // We have this extra temp here to slake GCC's thirst for the blood of those who dereference type-punned pointers. - void* temp = storage; - visitor.copyAndAppend(&temp, thisObject->structure()->outOfLineCapacity() * sizeof(WriteBarrierBase<Unknown>), storage->slot(), storageSize); - storage = static_cast<PropertyStorage>(temp); + void* temp = storage - capacity - 1; + visitor.copyAndAppend(&temp, capacity * sizeof(WriteBarrierBase<Unknown>), (storage - storageSize - 1)->slot(), storageSize); + storage = static_cast<PropertyStorage>(temp) + capacity + 1; thisObject->m_outOfLineStorage.set(storage, StorageBarrier::Unchecked); } @@ -128,10 +129,11 @@ void JSFinalObject::visitChildren(JSCell* cell, SlotVisitor& visitor) PropertyStorage storage = thisObject->outOfLineStorage(); if (storage) { size_t storageSize = thisObject->structure()->outOfLineSizeForKnownFinalObject(); + size_t capacity = thisObject->structure()->outOfLineCapacity(); // We have this extra temp here to slake GCC's thirst for the blood of those who dereference type-punned pointers. - void* temp = storage; - visitor.copyAndAppend(&temp, thisObject->structure()->outOfLineCapacity() * sizeof(WriteBarrierBase<Unknown>), storage->slot(), storageSize); - storage = static_cast<PropertyStorage>(temp); + void* temp = storage - capacity - 1; + visitor.copyAndAppend(&temp, thisObject->structure()->outOfLineCapacity() * sizeof(WriteBarrierBase<Unknown>), (storage - storageSize - 1)->slot(), storageSize); + storage = static_cast<PropertyStorage>(temp) + capacity + 1; thisObject->m_outOfLineStorage.set(storage, StorageBarrier::Unchecked); } @@ -595,7 +597,7 @@ PropertyStorage JSObject::growOutOfLineStorage(JSGlobalData& globalData, size_t // It's important that this function not rely on structure(), since // we might be in the middle of a transition. - + PropertyStorage oldPropertyStorage = m_outOfLineStorage.get(); PropertyStorage newPropertyStorage = 0; @@ -603,9 +605,9 @@ PropertyStorage JSObject::growOutOfLineStorage(JSGlobalData& globalData, size_t void* temp = newPropertyStorage; if (!globalData.heap.tryAllocateStorage(sizeof(WriteBarrierBase<Unknown>) * newSize, &temp)) CRASH(); - newPropertyStorage = static_cast<PropertyStorage>(temp); + newPropertyStorage = static_cast<PropertyStorage>(temp) + newSize + 1; - memcpy(newPropertyStorage, oldPropertyStorage, sizeof(WriteBarrierBase<Unknown>) * oldSize); + memcpy(newPropertyStorage - oldSize - 1, oldPropertyStorage - oldSize - 1, sizeof(WriteBarrierBase<Unknown>) * oldSize); ASSERT(newPropertyStorage); return newPropertyStorage; diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h index 9972d6077..cc43440ab 100644 --- a/Source/JavaScriptCore/runtime/JSObject.h +++ b/Source/JavaScriptCore/runtime/JSObject.h @@ -173,14 +173,14 @@ namespace JSC { { PropertyOffset offset = structure()->get(globalData, propertyName); checkOffset(offset, structure()->typeInfo().type()); - return offset != invalidOffset ? locationForOffset(offset) : 0; + return isValidOffset(offset) ? locationForOffset(offset) : 0; } WriteBarrierBase<Unknown>* getDirectLocation(JSGlobalData& globalData, PropertyName propertyName, unsigned& attributes) { JSCell* specificFunction; PropertyOffset offset = structure()->get(globalData, propertyName, attributes, specificFunction); - return offset != invalidOffset ? locationForOffset(offset) : 0; + return isValidOffset(offset) ? locationForOffset(offset) : 0; } bool hasInlineStorage() const { return structure()->hasInlineStorage(); } @@ -227,7 +227,7 @@ namespace JSC { if (offsetInInlineStorage < static_cast<size_t>(inlineStorageCapacity)) result = offsetInInlineStorage; else - result = location - outOfLineStorage() + firstOutOfLineOffset; + result = outOfLineStorage() - location + (inlineStorageCapacity - 2); validateOffset(result, structure()->typeInfo().type()); return result; } diff --git a/Source/JavaScriptCore/runtime/JSValue.h b/Source/JavaScriptCore/runtime/JSValue.h index 6f98bd6f7..19a8c4759 100644 --- a/Source/JavaScriptCore/runtime/JSValue.h +++ b/Source/JavaScriptCore/runtime/JSValue.h @@ -254,7 +254,7 @@ namespace JSC { JSValue structureOrUndefined() const; - char* description() const; + JS_EXPORT_PRIVATE char* description() const; JS_EXPORT_PRIVATE JSObject* synthesizePrototype(ExecState*) const; diff --git a/Source/JavaScriptCore/runtime/PropertyOffset.h b/Source/JavaScriptCore/runtime/PropertyOffset.h index c0d1316c4..3883d910f 100644 --- a/Source/JavaScriptCore/runtime/PropertyOffset.h +++ b/Source/JavaScriptCore/runtime/PropertyOffset.h @@ -118,7 +118,7 @@ inline size_t offsetInOutOfLineStorage(PropertyOffset offset) { validateOffset(offset); ASSERT(isOutOfLineOffset(offset)); - return offset - firstOutOfLineOffset; + return -static_cast<ptrdiff_t>(offset - firstOutOfLineOffset) - 2; } inline size_t offsetInRespectiveStorage(PropertyOffset offset) |