diff options
Diffstat (limited to 'Source/JavaScriptCore')
46 files changed, 884 insertions, 216 deletions
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog index 10fca607d..4eeefa508 100644 --- a/Source/JavaScriptCore/ChangeLog +++ b/Source/JavaScriptCore/ChangeLog @@ -1,20 +1,285 @@ -2012-06-13 Patrick Gansterer <paroga@webkit.org> +2012-07-23 Kent Tamura <tkent@chromium.org> - [WIN] Remove dependency on pthread from MachineStackMarker - https://bugs.webkit.org/show_bug.cgi?id=68429 + Rename ENABLE_METER_TAG and ENABLE_PROGRESS_TAG to ENABLE_METER_ELEMENT and ENABLE_PROGRESS_ELEMENT respectively + https://bugs.webkit.org/show_bug.cgi?id=91941 - Reviewed by NOBODY (OOPS!). + Reviewed by Kentaro Hara. - Implement pthread TLS functionality with native windows functions. + A flag name for an elmement should be ENABLE_*_ELEMENT. - * 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: + * Configurations/FeatureDefines.xcconfig: + +2012-07-22 Kent Tamura <tkent@chromium.org> + + Rename ENABLE_DETAILS to ENABLE_DETAILS_ELEMENT + https://bugs.webkit.org/show_bug.cgi?id=91928 + + Reviewed by Kentaro Hara. + + A flag name for an elmement should be ENABLE_*_ELEMENT. + + * Configurations/FeatureDefines.xcconfig: + +2012-07-21 Patrick Gansterer <paroga@webkit.org> + + [WIN] Use GetDateFormat and GetTimeFormat instead of strftime + https://bugs.webkit.org/show_bug.cgi?id=83436 + + Reviewed by Brent Fulgham. + + The MS CRT implementation of strftime calls the same two functions. + Using them directly avoids the overhead of parsing the format string and removes + the dependency on strftime() for WinCE where this function does not exist. + + * runtime/DatePrototype.cpp: + (JSC::formatLocaleDate): + +2012-07-20 Kent Tamura <tkent@chromium.org> + + Rename ENABLE_DATALIST to ENABLE_DATALIST_ELEMENT + https://bugs.webkit.org/show_bug.cgi?id=91846 + + Reviewed by Kentaro Hara. + + A flag name for an elmement should be ENABLE_*_ELEMENT. + + * Configurations/FeatureDefines.xcconfig: + +2012-07-20 Han Shen <shenhan@google.com> + + [Chromium] Compilation fails under gcc 4.7 + https://bugs.webkit.org/show_bug.cgi?id=90227 + + Reviewed by Tony Chang. + + Disable warnings about c++0x compatibility in gcc newer than 4.6. + + * JavaScriptCore.gyp/JavaScriptCore.gyp: + +2012-07-18 Filip Pizlo <fpizlo@apple.com> + + DFG cell checks should be hoisted + https://bugs.webkit.org/show_bug.cgi?id=91717 + + Reviewed by Geoffrey Garen. + + The DFG has always had the policy of hoisting array and integer checks to + the point of variable assignment. Eventually, we added doubles and booleans + to the mix. But cells should really be part of this as well, particularly + for 32-bit where accessing a known-type variable is dramatically cheaper + than accessing a variable whose types is only predicted but otherwise + unproven. + + This appears to be a definite speed-up for V8 on 32-bit, a possible speed-up + for Kraken, and a possible slow-down for V8 on 64-bit (around 0.2% if at + all). Any slow-downs can, and should, be addressed by making the hoisting + logic cognizant of variables that are never used in a manner that requires + type checks, and by sinking argument checks to the point(s) of first use. + + To make this work I had to change some OSR machinery, and special-case the + type predictions of the 'this' argument for constructors. OSR exit normally + assumes that arguments are boxed, which happens to be true because the + type prediction used for check hoisting is LUB'd with the type of the + argument that was passed in - so either the arguments are always stored to + with the full tag+payload, or if only the payload is stored then the tag + matches whatever the caller would have set. But not so with the 'this' + argument for constructors, which is not initialized by the caller. We + could make this more precise by having argument types for OSR be inferred + using similar machinery to other locals, but I figured that for this patch + I should use the surgical fix. + + * assembler/MacroAssemblerX86_64.h: + (JSC::MacroAssemblerX86_64::branchTestPtr): + (MacroAssemblerX86_64): + * assembler/X86Assembler.h: + (JSC::X86Assembler::testq_rm): + (X86Assembler): + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::initialize): + (JSC::DFG::AbstractState::execute): + * dfg/DFGDriver.cpp: + (JSC::DFG::compile): + * dfg/DFGGraph.h: + (JSC::DFG::Graph::isCreatedThisArgument): + (Graph): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::checkArgumentTypes): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGValueSource.h: + (JSC::DFG::ValueSource::forSpeculation): + +2012-07-19 Filip Pizlo <fpizlo@apple.com> + + Fast path of storage resize should be removed from property storage reallocation, since it is only useful for arrays + https://bugs.webkit.org/show_bug.cgi?id=91796 + + Reviewed by Geoffrey Garen. + + * dfg/DFGRepatch.cpp: + (JSC::DFG::emitPutTransitionStub): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compileReallocatePropertyStorage): + * runtime/JSObject.cpp: + (JSC::JSObject::growOutOfLineStorage): + +2012-07-19 Mark Lam <mark.lam@apple.com> + + Bug fixes and enhancements for OfflineASM annotation system. + https://bugs.webkit.org/show_bug.cgi?id=91690 + + Reviewed by Filip Pizlo. + + * offlineasm/armv7.rb: added default handling of Instruction lower(). + * offlineasm/asm.rb: added more support for annotations and more pretty printing. + * offlineasm/ast.rb: added more support for annotations. + * offlineasm/config.rb: added $preferredCommentStartColumn, simplified $enableInstrAnnotations. + * offlineasm/parser.rb: added more support for annotations. + * offlineasm/transform.rb: added more support for annotations. + * offlineasm/x86.rb: added default handling of Instruction lower(). + +2012-07-19 Patrick Gansterer <paroga@webkit.org> + + [WIN] Fix compilation of JSGlobalData.h with ENABLE(DFG_JIT) + https://bugs.webkit.org/show_bug.cgi?id=91243 + + Reviewed by Geoffrey Garen. + + Disable MSVC warning 4200 "zero-sized array in struct/union" for JSC::ScratchBuffer. + + * runtime/JSGlobalData.h: + (JSC): + +2012-07-19 Mark Lam <mark.lam@apple.com> + + Fixed broken ENABLE_JIT=0 build. + https://bugs.webkit.org/show_bug.cgi?id=91725 + + Reviewed by Oliver Hunt. + + * bytecode/Watchpoint.cpp: + * heap/JITStubRoutineSet.h: + (JSC): + (JITStubRoutineSet): + (JSC::JITStubRoutineSet::JITStubRoutineSet): + (JSC::JITStubRoutineSet::~JITStubRoutineSet): + (JSC::JITStubRoutineSet::add): + (JSC::JITStubRoutineSet::clearMarks): + (JSC::JITStubRoutineSet::mark): + (JSC::JITStubRoutineSet::deleteUnmarkedJettisonedStubRoutines): + (JSC::JITStubRoutineSet::traceMarkedStubRoutines): + +2012-07-19 Kristóf Kosztyó <kkristof@inf.u-szeged.hu> + + [Qt] Unreviewed buildfix after r123042. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::dumpRegisters): + +2012-07-18 Filip Pizlo <fpizlo@apple.com> + + DFG should emit inline code for property storage (re)allocation + https://bugs.webkit.org/show_bug.cgi?id=91597 + + Reviewed by Oliver Hunt. + + This adds two new ops to the DFG IR: AllocatePropertyStorage and + ReallocatePropertyStorage. It enables these to interact properly with + CSE so that a GetPropertyStorage on something for which we have + obviously done a (Re)AllocatePropertyStorage will result in the + GetPropertyStorage being eliminated. Other than that, the code + emitted for these ops is identical to the code we were emitting in + the corresponding PutById stub. + + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::execute): + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::parseBlock): + * dfg/DFGCSEPhase.cpp: + (JSC::DFG::CSEPhase::putStructureStoreElimination): + (JSC::DFG::CSEPhase::getPropertyStorageLoadElimination): + * dfg/DFGNode.h: + (JSC::DFG::Node::hasStructureTransitionData): + * dfg/DFGNodeType.h: + (DFG): + * dfg/DFGOperations.cpp: + * dfg/DFGOperations.h: + * dfg/DFGPredictionPropagationPhase.cpp: + (JSC::DFG::PredictionPropagationPhase::propagate): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compileAllocatePropertyStorage): + (DFG): + (JSC::DFG::SpeculativeJIT::compileReallocatePropertyStorage): + * dfg/DFGSpeculativeJIT.h: + (JSC::DFG::SpeculativeJIT::callOperation): + (SpeculativeJIT): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * runtime/Structure.cpp: + (JSC::nextOutOfLineStorageCapacity): + * runtime/Structure.h: + (JSC): + +2012-07-16 Oliver Hunt <oliver@apple.com> + + dumpCallFrame is broken in ToT + https://bugs.webkit.org/show_bug.cgi?id=91444 + + Reviewed by Gavin Barraclough. + + Various changes have been made to the SF calling convention, but + dumpCallFrame has not been updated to reflect these changes. + That resulted in both bogus information, as well as numerous + assertions of sadness. + + This patch makes dumpCallFrame actually work again and adds the + wonderful feature of telling you the name of the variable that a + register reflects, or what value it contains. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::nameForRegister): + A really innefficient mechanism for finding the name of a local register. + This should only ever be used by debug code so this should be okay. + * bytecode/CodeBlock.h: + (CodeBlock): + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::generate): + Debug builds no longer throw away a functions symbol table, this allows + us to actually perform a register# to name mapping + * dfg/DFGJITCompiler.cpp: + (JSC::DFG::JITCompiler::link): + We weren't propogating the bytecode offset here leading to assertions + in debug builds when dumping bytecode of DFG compiled code. + * interpreter/Interpreter.cpp: + (JSC): + (JSC::Interpreter::dumpRegisters): + Rework to actually be correct. + (JSC::getCallerInfo): + Return the byteocde offset as well now, given we have to determine it + anyway. + (JSC::Interpreter::getStackTrace): + (JSC::Interpreter::retrieveCallerFromVMCode): + * interpreter/Interpreter.h: + (Interpreter): + * jsc.cpp: + (GlobalObject::finishCreation): + (functionDumpCallFrame): + Give debug builds of JSC a method for calling dumpCallFrame so we can + inspect a callframe without requiring us to break in a debugger. + +2012-07-18 Filip Pizlo <fpizlo@apple.com> + + DFG 32-bit PutById transition stub storage reallocation case copies the first pointer of each JSValue instead of the whole JSValue + https://bugs.webkit.org/show_bug.cgi?id=91599 + + Reviewed by Geoffrey Garen. + + * dfg/DFGRepatch.cpp: + (JSC::DFG::emitPutTransitionStub): 2012-07-17 Filip Pizlo <fpizlo@apple.com> diff --git a/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig b/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig index dcea98333..31853f34c 100644 --- a/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig +++ b/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig @@ -48,9 +48,9 @@ ENABLE_CSS_VARIABLES = ; ENABLE_CUSTOM_SCHEME_HANDLER = ; ENABLE_DASHBOARD_SUPPORT = $(ENABLE_DASHBOARD_SUPPORT_$(REAL_PLATFORM_NAME)); ENABLE_DASHBOARD_SUPPORT_macosx = ENABLE_DASHBOARD_SUPPORT; -ENABLE_DATALIST = ; +ENABLE_DATALIST_ELEMENT = ; ENABLE_DATA_TRANSFER_ITEMS = ; -ENABLE_DETAILS = ENABLE_DETAILS; +ENABLE_DETAILS_ELEMENT = ENABLE_DETAILS_ELEMENT; ENABLE_DEVICE_ORIENTATION = ; ENABLE_DIALOG_ELEMENT = ; ENABLE_DIRECTORY_UPLOAD = ; @@ -97,7 +97,7 @@ ENABLE_LINK_PRERENDER = ; ENABLE_MATHML = ENABLE_MATHML; ENABLE_MEDIA_SOURCE = ; ENABLE_MEDIA_STATISTICS = ; -ENABLE_METER_TAG = ENABLE_METER_TAG; +ENABLE_METER_ELEMENT = ENABLE_METER_ELEMENT; ENABLE_MHTML = ; ENABLE_MICRODATA = ; ENABLE_MUTATION_OBSERVERS = ENABLE_MUTATION_OBSERVERS; @@ -107,7 +107,7 @@ ENABLE_NOTIFICATIONS_macosx_1070 = ; ENABLE_NOTIFICATIONS_macosx_1080 = ENABLE_NOTIFICATIONS; ENABLE_NOTIFICATIONS_macosx_1090 = ENABLE_NOTIFICATIONS; ENABLE_PAGE_VISIBILITY_API = ; -ENABLE_PROGRESS_TAG = ENABLE_PROGRESS_TAG; +ENABLE_PROGRESS_ELEMENT = ENABLE_PROGRESS_ELEMENT; ENABLE_QUOTA = ; ENABLE_REGISTER_PROTOCOL_HANDLER = ; ENABLE_REQUEST_ANIMATION_FRAME = ENABLE_REQUEST_ANIMATION_FRAME; @@ -134,4 +134,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) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS) $(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_TAG) $(ENABLE_MICRODATA) $(ENABLE_MUTATION_OBSERVERS) $(ENABLE_NOTIFICATIONS) $(ENABLE_PAGE_VISIBILITY_API) $(ENABLE_PROGRESS_TAG) $(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_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); diff --git a/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp b/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp index c60a2e68d..4f7a205e7 100644 --- a/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp +++ b/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp @@ -47,7 +47,7 @@ ], }, 'conditions': [ - ['os_posix == 1 and OS != "mac" and gcc_version==46', { + ['os_posix == 1 and OS != "mac" and gcc_version>=46', { 'target_defaults': { # Disable warnings about c++0x compatibility, as some names (such as nullptr) conflict # with upcoming c++0x types. 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/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def index dfa38aafb..d8f838e87 100755 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def @@ -163,6 +163,7 @@ EXPORTS ?displayName@JSFunction@JSC@@QAE?BVUString@2@PAVExecState@2@@Z ?dtoa@WTF@@YAXQADNAA_NAAHAAI@Z ?dumpAllOptions@Options@JSC@@SAXPAU_iobuf@@@Z + ?dumpCallFrame@Interpreter@JSC@@QAEXPAVExecState@2@@Z ?dumpSampleData@JSGlobalData@JSC@@QAEXPAVExecState@2@@Z ?empty@StringImpl@WTF@@SAPAV12@XZ ?enumerable@PropertyDescriptor@JSC@@QBE_NXZ diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h b/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h index 43bcddb64..f5af51323 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h @@ -476,6 +476,12 @@ public: return Jump(m_assembler.jCC(x86Condition(cond))); } + Jump branchTestPtr(ResultCondition cond, Address address, RegisterID reg) + { + m_assembler.testq_rm(reg, address.offset, address.base); + return Jump(m_assembler.jCC(x86Condition(cond))); + } + Jump branchTestPtr(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1)) { if (mask.m_value == -1) diff --git a/Source/JavaScriptCore/assembler/X86Assembler.h b/Source/JavaScriptCore/assembler/X86Assembler.h index 83d681cf7..fc1c27245 100644 --- a/Source/JavaScriptCore/assembler/X86Assembler.h +++ b/Source/JavaScriptCore/assembler/X86Assembler.h @@ -997,6 +997,11 @@ public: m_formatter.oneByteOp64(OP_TEST_EvGv, src, dst); } + void testq_rm(RegisterID src, int offset, RegisterID base) + { + m_formatter.oneByteOp64(OP_TEST_EvGv, src, base, offset); + } + void testq_i32r(int imm, RegisterID dst) { m_formatter.oneByteOp64(OP_GROUP3_EvIz, GROUP3_OP_TEST, dst); diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp index d417a5fbd..363efa28a 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp +++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp @@ -2942,4 +2942,29 @@ bool CodeBlock::usesOpcode(OpcodeID opcodeID) return false; } +UString CodeBlock::nameForRegister(int registerNumber) +{ + SymbolTable::iterator end = m_symbolTable->end(); + for (SymbolTable::iterator ptr = m_symbolTable->begin(); ptr != end; ++ptr) { + if (ptr->second.getIndex() == registerNumber) + return UString(ptr->first); + } + if (needsActivation() && registerNumber == activationRegister()) + return "activation"; + if (registerNumber == thisRegister()) + return "this"; + if (usesArguments()) { + if (registerNumber == argumentsRegister()) + return "arguments"; + if (unmodifiedArgumentsRegister(argumentsRegister()) == registerNumber) + return "real arguments"; + } + if (registerNumber < 0) { + int argumentPosition = -registerNumber; + argumentPosition -= RegisterFile::CallFrameHeaderSize + 1; + return String::format("arguments[%3d]", argumentPosition - 1).impl(); + } + return ""; +} + } // namespace JSC diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h index 56ede595a..2a7d2120a 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.h +++ b/Source/JavaScriptCore/bytecode/CodeBlock.h @@ -578,7 +578,9 @@ namespace JSC { void createActivation(CallFrame*); void clearEvalCache(); - + + UString nameForRegister(int registerNumber); + void addPropertyAccessInstruction(unsigned propertyAccessInstruction) { m_propertyAccessInstructions.append(propertyAccessInstruction); diff --git a/Source/JavaScriptCore/bytecode/Watchpoint.cpp b/Source/JavaScriptCore/bytecode/Watchpoint.cpp index 6f80dfa5e..75dfe8a76 100644 --- a/Source/JavaScriptCore/bytecode/Watchpoint.cpp +++ b/Source/JavaScriptCore/bytecode/Watchpoint.cpp @@ -27,6 +27,7 @@ #include "Watchpoint.h" #include "LinkBuffer.h" +#include <wtf/PassRefPtr.h> namespace JSC { diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp index b104788c8..33f282c66 100644 --- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp +++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp @@ -193,8 +193,10 @@ JSObject* BytecodeGenerator::generate() if (s_dumpsGeneratedCode) m_codeBlock->dump(m_scopeChain->globalObject->globalExec()); +#ifdef NDEBUG if ((m_codeType == FunctionCode && !m_codeBlock->needsFullScopeChain() && !m_codeBlock->usesArguments()) || m_codeType == EvalCode) symbolTable().clear(); +#endif m_codeBlock->shrinkToFit(CodeBlock::EarlyShrink); diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp index e4561da06..01996f132 100644 --- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp +++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp @@ -128,6 +128,8 @@ void AbstractState::initialize(Graph& graph) root->valuesAtHead.argument(i).set(SpecFloat32Array); else if (isFloat64ArraySpeculation(prediction)) root->valuesAtHead.argument(i).set(SpecFloat64Array); + else if (isCellSpeculation(prediction)) + root->valuesAtHead.argument(i).set(SpecCell); else root->valuesAtHead.argument(i).makeTop(); @@ -272,7 +274,8 @@ bool AbstractState::execute(unsigned indexInBlock) } case SetLocal: { - if (node.variableAccessData()->isCaptured()) { + if (node.variableAccessData()->isCaptured() + || m_graph.isCreatedThisArgument(node.local())) { m_variables.operand(node.local()) = forNode(node.child1()); node.setCanExit(false); break; @@ -290,6 +293,9 @@ bool AbstractState::execute(unsigned indexInBlock) else if (isArraySpeculation(predictedType)) { node.setCanExit(!isArraySpeculation(forNode(node.child1()).m_type)); forNode(node.child1()).filter(SpecArray); + } else if (isCellSpeculation(predictedType)) { + node.setCanExit(!isCellSpeculation(forNode(node.child1()).m_type)); + forNode(node.child1()).filter(SpecCell); } else if (isBooleanSpeculation(predictedType)) speculateBooleanUnary(node); else @@ -1437,6 +1443,8 @@ bool AbstractState::execute(unsigned indexInBlock) m_haveStructures = true; break; case GetPropertyStorage: + case AllocatePropertyStorage: + case ReallocatePropertyStorage: node.setCanExit(false); forNode(node.child1()).filter(SpecCell); forNode(nodeIndex).clear(); // The result is not a JS value. diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp index 1b1395934..e4e94e90b 100644 --- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp +++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp @@ -2271,7 +2271,6 @@ bool ByteCodeParser::parseBlock(unsigned limit) m_graph.m_storageAccessData.append(storageAccessData); } else if (!hasExitSite && putByIdStatus.isSimpleTransition() - && putByIdStatus.oldStructure()->outOfLineCapacity() == putByIdStatus.newStructure()->outOfLineCapacity() && structureChainIsStillValid( direct, putByIdStatus.oldStructure(), @@ -2293,20 +2292,38 @@ bool ByteCodeParser::parseBlock(unsigned limit) } } ASSERT(putByIdStatus.oldStructure()->transitionWatchpointSetHasBeenInvalidated()); - addToGraph( - PutStructure, - OpInfo( - m_graph.addStructureTransitionData( - StructureTransitionData( - putByIdStatus.oldStructure(), - putByIdStatus.newStructure()))), - base); NodeIndex propertyStorage; - if (isInlineOffset(putByIdStatus.offset())) - propertyStorage = base; - else - propertyStorage = addToGraph(GetPropertyStorage, base); + StructureTransitionData* transitionData = + m_graph.addStructureTransitionData( + StructureTransitionData( + putByIdStatus.oldStructure(), + putByIdStatus.newStructure())); + + if (putByIdStatus.oldStructure()->outOfLineCapacity() + != putByIdStatus.newStructure()->outOfLineCapacity()) { + + // If we're growing the property storage then it must be because we're + // storing into the out-of-line storage. + ASSERT(!isInlineOffset(putByIdStatus.offset())); + + if (!putByIdStatus.oldStructure()->outOfLineCapacity()) { + propertyStorage = addToGraph( + AllocatePropertyStorage, OpInfo(transitionData), base); + } else { + propertyStorage = addToGraph( + ReallocatePropertyStorage, OpInfo(transitionData), + base, addToGraph(GetPropertyStorage, base)); + } + } else { + if (isInlineOffset(putByIdStatus.offset())) + propertyStorage = base; + else + propertyStorage = addToGraph(GetPropertyStorage, base); + } + + addToGraph(PutStructure, OpInfo(transitionData), base); + addToGraph( PutByOffset, OpInfo(m_graph.m_storageAccessData.size()), diff --git a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp index 04c3ebc66..4532214ee 100644 --- a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp @@ -465,6 +465,8 @@ private: case NewArray: case NewObject: case CreateThis: + case AllocatePropertyStorage: + case ReallocatePropertyStorage: return NoNode; default: @@ -581,6 +583,17 @@ private: if (node.child1() == child1) return index; break; + + case AllocatePropertyStorage: + case ReallocatePropertyStorage: + // If we can cheaply prove this is a change to our object's storage, we + // can optimize and use its result. + if (node.child1() == child1) + return index; + // Otherwise, we currently can't prove that this doesn't change our object's + // storage, so we conservatively assume that it may change the storage + // pointer of any object, including ours. + return NoNode; case PutByOffset: case PutStructure: diff --git a/Source/JavaScriptCore/dfg/DFGDriver.cpp b/Source/JavaScriptCore/dfg/DFGDriver.cpp index 64fc0c7e5..f160b6d35 100644 --- a/Source/JavaScriptCore/dfg/DFGDriver.cpp +++ b/Source/JavaScriptCore/dfg/DFGDriver.cpp @@ -64,7 +64,7 @@ inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo if (!Options::useDFGJIT()) return false; - + #if DFG_ENABLE(DEBUG_VERBOSE) dataLog("DFG compiling code block %p(%p) for executable %p, number of instructions = %u.\n", codeBlock, codeBlock->alternative(), codeBlock->ownerExecutable(), codeBlock->instructionCount()); #endif diff --git a/Source/JavaScriptCore/dfg/DFGGraph.h b/Source/JavaScriptCore/dfg/DFGGraph.h index 4091c48f7..3e6539353 100644 --- a/Source/JavaScriptCore/dfg/DFGGraph.h +++ b/Source/JavaScriptCore/dfg/DFGGraph.h @@ -441,6 +441,15 @@ public: return m_codeBlock->usesArguments(); } + bool isCreatedThisArgument(int operand) + { + if (!operandIsArgument(operand)) + return false; + if (operandToArgument(operand)) + return false; + return m_codeBlock->specializationKind() == CodeForConstruct; + } + unsigned numSuccessors(BasicBlock* block) { return at(block->last()).numSuccessors(); diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp index 5a9f972b8..ae28fad3f 100644 --- a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp +++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp @@ -188,6 +188,7 @@ void JITCompiler::link(LinkBuffer& linkBuffer) CallLinkInfo& info = m_codeBlock->callLinkInfo(i); info.callType = m_jsCalls[i].m_callType; info.isDFG = true; + info.bytecodeIndex = m_jsCalls[i].m_codeOrigin.bytecodeIndex; linkBuffer.link(m_jsCalls[i].m_slowCall, FunctionPtr((m_globalData->getCTIStub(info.callType == CallLinkInfo::Construct ? linkConstructThunkGenerator : linkCallThunkGenerator)).code().executableAddress())); info.callReturnLocation = linkBuffer.locationOfNearCall(m_jsCalls[i].m_slowCall); info.hotPathBegin = linkBuffer.locationOf(m_jsCalls[i].m_targetToCheck); diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h index ae07d5512..e72bd5e36 100644 --- a/Source/JavaScriptCore/dfg/DFGNode.h +++ b/Source/JavaScriptCore/dfg/DFGNode.h @@ -632,7 +632,15 @@ struct Node { bool hasStructureTransitionData() { - return op() == PutStructure || op() == PhantomPutStructure; + switch (op()) { + case PutStructure: + case PhantomPutStructure: + case AllocatePropertyStorage: + case ReallocatePropertyStorage: + return true; + default: + return false; + } } StructureTransitionData& structureTransitionData() diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h index 7fcd2ec14..0ca0039b9 100644 --- a/Source/JavaScriptCore/dfg/DFGNodeType.h +++ b/Source/JavaScriptCore/dfg/DFGNodeType.h @@ -133,6 +133,8 @@ namespace JSC { namespace DFG { macro(StructureTransitionWatchpoint, NodeMustGenerate) \ macro(PutStructure, NodeMustGenerate) \ macro(PhantomPutStructure, NodeMustGenerate | NodeDoesNotExit) \ + macro(AllocatePropertyStorage, NodeMustGenerate | NodeDoesNotExit | NodeResultStorage) \ + macro(ReallocatePropertyStorage, NodeMustGenerate | NodeDoesNotExit | NodeResultStorage) \ macro(GetPropertyStorage, NodeResultStorage) \ macro(GetIndexedPropertyStorage, NodeMustGenerate | NodeResultStorage) \ macro(GetByOffset, NodeResultJS) \ diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp index 03c0666b7..9050d590e 100644 --- a/Source/JavaScriptCore/dfg/DFGOperations.cpp +++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp @@ -28,6 +28,7 @@ #include "Arguments.h" #include "CodeBlock.h" +#include "CopiedSpaceInlineMethods.h" #include "DFGOSRExit.h" #include "DFGRepatch.h" #include "DFGThunks.h" @@ -894,7 +895,7 @@ static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializ return globalData->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(); } -inline void* linkFor(ExecState* execCallee, CodeSpecializationKind kind) +inline char* linkFor(ExecState* execCallee, CodeSpecializationKind kind) { ExecState* exec = execCallee->callerFrame(); JSGlobalData* globalData = &exec->globalData(); @@ -903,7 +904,7 @@ inline void* linkFor(ExecState* execCallee, CodeSpecializationKind kind) JSValue calleeAsValue = execCallee->calleeAsValue(); JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue); if (!calleeAsFunctionCell) - return handleHostCall(execCallee, calleeAsValue, kind); + return reinterpret_cast<char*>(handleHostCall(execCallee, calleeAsValue, kind)); JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell); execCallee->setScopeChain(callee->scopeUnchecked()); @@ -918,7 +919,7 @@ inline void* linkFor(ExecState* execCallee, CodeSpecializationKind kind) JSObject* error = functionExecutable->compileFor(execCallee, callee->scope(), kind); if (error) { globalData->exception = createStackOverflowError(exec); - return globalData->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(); + return reinterpret_cast<char*>(globalData->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress()); } codeBlock = &functionExecutable->generatedBytecodeFor(kind); if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters())) @@ -931,20 +932,20 @@ inline void* linkFor(ExecState* execCallee, CodeSpecializationKind kind) callLinkInfo.setSeen(); else dfgLinkFor(execCallee, callLinkInfo, codeBlock, callee, codePtr, kind); - return codePtr.executableAddress(); + return reinterpret_cast<char*>(codePtr.executableAddress()); } -void* DFG_OPERATION operationLinkCall(ExecState* execCallee) +char* DFG_OPERATION operationLinkCall(ExecState* execCallee) { return linkFor(execCallee, CodeForCall); } -void* DFG_OPERATION operationLinkConstruct(ExecState* execCallee) +char* DFG_OPERATION operationLinkConstruct(ExecState* execCallee) { return linkFor(execCallee, CodeForConstruct); } -inline void* virtualFor(ExecState* execCallee, CodeSpecializationKind kind) +inline char* virtualFor(ExecState* execCallee, CodeSpecializationKind kind) { ExecState* exec = execCallee->callerFrame(); JSGlobalData* globalData = &exec->globalData(); @@ -953,7 +954,7 @@ inline void* virtualFor(ExecState* execCallee, CodeSpecializationKind kind) JSValue calleeAsValue = execCallee->calleeAsValue(); JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue); if (UNLIKELY(!calleeAsFunctionCell)) - return handleHostCall(execCallee, calleeAsValue, kind); + return reinterpret_cast<char*>(handleHostCall(execCallee, calleeAsValue, kind)); JSFunction* function = jsCast<JSFunction*>(calleeAsFunctionCell); execCallee->setScopeChain(function->scopeUnchecked()); @@ -963,18 +964,18 @@ inline void* virtualFor(ExecState* execCallee, CodeSpecializationKind kind) JSObject* error = functionExecutable->compileFor(execCallee, function->scope(), kind); if (error) { exec->globalData().exception = error; - return globalData->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(); + return reinterpret_cast<char*>(globalData->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress()); } } - return executable->generatedJITCodeWithArityCheckFor(kind).executableAddress(); + return reinterpret_cast<char*>(executable->generatedJITCodeWithArityCheckFor(kind).executableAddress()); } -void* DFG_OPERATION operationVirtualCall(ExecState* execCallee) +char* DFG_OPERATION operationVirtualCall(ExecState* execCallee) { return virtualFor(execCallee, CodeForCall); } -void* DFG_OPERATION operationVirtualConstruct(ExecState* execCallee) +char* DFG_OPERATION operationVirtualConstruct(ExecState* execCallee) { return virtualFor(execCallee, CodeForConstruct); } @@ -1241,6 +1242,24 @@ void DFG_OPERATION operationReallocateStorageAndFinishPut(ExecState* exec, JSObj base->putDirectOffset(globalData, offset, JSValue::decode(value)); } +char* DFG_OPERATION operationAllocatePropertyStorageWithInitialCapacity(ExecState* exec) +{ + JSGlobalData& globalData = exec->globalData(); + void* result; + if (!globalData.heap.tryAllocateStorage(initialOutOfLineCapacity * sizeof(JSValue), &result)) + CRASH(); + return reinterpret_cast<char*>(result); +} + +char* DFG_OPERATION operationAllocatePropertyStorage(ExecState* exec, size_t newSize) +{ + JSGlobalData& globalData = exec->globalData(); + void* result; + if (!globalData.heap.tryAllocateStorage(newSize, &result)) + CRASH(); + return reinterpret_cast<char*>(result); +} + double DFG_OPERATION operationFModOnInts(int32_t a, int32_t b) { return fmod(a, b); diff --git a/Source/JavaScriptCore/dfg/DFGOperations.h b/Source/JavaScriptCore/dfg/DFGOperations.h index 109dcb2eb..d0fbf7ed4 100644 --- a/Source/JavaScriptCore/dfg/DFGOperations.h +++ b/Source/JavaScriptCore/dfg/DFGOperations.h @@ -104,7 +104,8 @@ typedef void DFG_OPERATION (*V_DFGOperation_EJJJ)(ExecState*, EncodedJSValue, En typedef void DFG_OPERATION (*V_DFGOperation_EJPP)(ExecState*, EncodedJSValue, EncodedJSValue, void*); typedef void DFG_OPERATION (*V_DFGOperation_EPZJ)(ExecState*, void*, int32_t, EncodedJSValue); typedef void DFG_OPERATION (*V_DFGOperation_W)(WatchpointSet*); -typedef void* DFG_OPERATION (*P_DFGOperation_E)(ExecState*); +typedef char* DFG_OPERATION (*P_DFGOperation_E)(ExecState*); +typedef char* DFG_OPERATION (*P_DFGOperation_ES)(ExecState*, size_t); // These routines are provide callbacks out to C++ implementations of operations too complex to JIT. JSCell* DFG_OPERATION operationNewObject(ExecState*) WTF_INTERNAL; @@ -162,10 +163,10 @@ size_t DFG_OPERATION operationCompareGreaterEq(ExecState*, EncodedJSValue encode size_t DFG_OPERATION operationCompareEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL; size_t DFG_OPERATION operationCompareStrictEqCell(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL; size_t DFG_OPERATION operationCompareStrictEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL; -void* DFG_OPERATION operationVirtualCall(ExecState*) WTF_INTERNAL; -void* DFG_OPERATION operationLinkCall(ExecState*) WTF_INTERNAL; -void* DFG_OPERATION operationVirtualConstruct(ExecState*) WTF_INTERNAL; -void* DFG_OPERATION operationLinkConstruct(ExecState*) WTF_INTERNAL; +char* DFG_OPERATION operationVirtualCall(ExecState*) WTF_INTERNAL; +char* DFG_OPERATION operationLinkCall(ExecState*) WTF_INTERNAL; +char* DFG_OPERATION operationVirtualConstruct(ExecState*) WTF_INTERNAL; +char* DFG_OPERATION operationLinkConstruct(ExecState*) WTF_INTERNAL; JSCell* DFG_OPERATION operationCreateActivation(ExecState*) WTF_INTERNAL; JSCell* DFG_OPERATION operationCreateArguments(ExecState*) WTF_INTERNAL; JSCell* DFG_OPERATION operationCreateInlinedArguments(ExecState*, InlineCallFrame*) WTF_INTERNAL; @@ -181,6 +182,8 @@ double DFG_OPERATION operationFModOnInts(int32_t, int32_t) WTF_INTERNAL; size_t DFG_OPERATION operationIsObject(EncodedJSValue) WTF_INTERNAL; size_t DFG_OPERATION operationIsFunction(EncodedJSValue) WTF_INTERNAL; void DFG_OPERATION operationReallocateStorageAndFinishPut(ExecState*, JSObject*, Structure*, PropertyOffset, EncodedJSValue) WTF_INTERNAL; +char* DFG_OPERATION operationAllocatePropertyStorageWithInitialCapacity(ExecState*) WTF_INTERNAL; +char* DFG_OPERATION operationAllocatePropertyStorage(ExecState*, size_t newSize) WTF_INTERNAL; // This method is used to lookup an exception hander, keyed by faultLocation, which is // the return location from one of the calls out to one of the helper operations above. diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp index d23cd8265..2e4f8094c 100644 --- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp @@ -449,7 +449,9 @@ private: } case GetPropertyStorage: - case GetIndexedPropertyStorage: { + case GetIndexedPropertyStorage: + case AllocatePropertyStorage: + case ReallocatePropertyStorage: { changed |= setPrediction(SpecOther); changed |= mergeDefaultFlags(node); break; diff --git a/Source/JavaScriptCore/dfg/DFGRepatch.cpp b/Source/JavaScriptCore/dfg/DFGRepatch.cpp index cfc2cd664..19e064f2c 100644 --- a/Source/JavaScriptCore/dfg/DFGRepatch.cpp +++ b/Source/JavaScriptCore/dfg/DFGRepatch.cpp @@ -829,33 +829,18 @@ static void emitPutTransitionStub( size_t oldSize = oldStructure->outOfLineCapacity() * sizeof(JSValue); ASSERT(newSize > oldSize); - // Optimistically assume that the old storage was the very last thing - // allocated. stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::offsetOfOutOfLineStorage()), scratchGPR3); - stubJit.loadPtr(&copiedAllocator->m_currentPayloadEnd, scratchGPR2); stubJit.loadPtr(&copiedAllocator->m_currentRemaining, scratchGPR1); - stubJit.subPtr(scratchGPR1, scratchGPR2); - stubJit.subPtr(MacroAssembler::TrustedImm32(oldSize), scratchGPR2); - MacroAssembler::Jump needFullRealloc = - stubJit.branchPtr(MacroAssembler::NotEqual, scratchGPR2, scratchGPR3); - slowPath.append(stubJit.branchSubPtr(MacroAssembler::Signed, MacroAssembler::TrustedImm32(newSize - oldSize), scratchGPR1)); - stubJit.storePtr(scratchGPR1, &copiedAllocator->m_currentRemaining); - stubJit.move(scratchGPR2, scratchGPR1); - MacroAssembler::Jump doneRealloc = stubJit.jump(); - - needFullRealloc.link(&stubJit); slowPath.append(stubJit.branchSubPtr(MacroAssembler::Signed, MacroAssembler::TrustedImm32(newSize), scratchGPR1)); stubJit.storePtr(scratchGPR1, &copiedAllocator->m_currentRemaining); stubJit.negPtr(scratchGPR1); stubJit.addPtr(MacroAssembler::AbsoluteAddress(&copiedAllocator->m_currentPayloadEnd), scratchGPR1); stubJit.subPtr(MacroAssembler::TrustedImm32(newSize), scratchGPR1); // We have scratchGPR1 = new storage, scratchGPR3 = old storage, scratchGPR2 = available - for (size_t offset = 0; offset < oldSize; offset += sizeof(JSValue)) { + for (size_t offset = 0; offset < oldSize; offset += sizeof(void*)) { stubJit.loadPtr(MacroAssembler::Address(scratchGPR3, offset), scratchGPR2); stubJit.storePtr(scratchGPR2, MacroAssembler::Address(scratchGPR1, offset)); } - - doneRealloc.link(&stubJit); } stubJit.storePtr(scratchGPR1, MacroAssembler::Address(baseGPR, JSObject::offsetOfOutOfLineStorage())); diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp index e8824b832..f368cf298 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp @@ -1241,7 +1241,8 @@ void SpeculativeJIT::checkArgumentTypes() m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr()); speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister)); speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float64ArrayDescriptor().m_classInfo))); - } + } else if (isCellSpeculation(predictedType)) + speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, JITCompiler::addressFor(virtualRegister), GPRInfo::tagMaskRegister)); #else if (isInt32Speculation(predictedType)) speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag))); @@ -1307,7 +1308,8 @@ void SpeculativeJIT::checkArgumentTypes() speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag))); m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr()); speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float64ArrayDescriptor().m_classInfo))); - } + } else if (isCellSpeculation(predictedType)) + speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::CellTag))); #endif } m_isCheckingArgumentTypes = false; @@ -3137,6 +3139,72 @@ bool SpeculativeJIT::compileRegExpExec(Node& node) return true; } +void SpeculativeJIT::compileAllocatePropertyStorage(Node& node) +{ + SpeculateCellOperand base(this, node.child1()); + GPRTemporary scratch(this); + + GPRReg baseGPR = base.gpr(); + GPRReg scratchGPR = scratch.gpr(); + + ASSERT(!node.structureTransitionData().previousStructure->outOfLineCapacity()); + ASSERT(initialOutOfLineCapacity == node.structureTransitionData().newStructure->outOfLineCapacity()); + size_t newSize = initialOutOfLineCapacity * sizeof(JSValue); + CopiedAllocator* copiedAllocator = &m_jit.globalData()->heap.storageAllocator(); + + m_jit.loadPtr(&copiedAllocator->m_currentRemaining, scratchGPR); + JITCompiler::Jump slowPath = m_jit.branchSubPtr(JITCompiler::Signed, JITCompiler::TrustedImm32(newSize), scratchGPR); + 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); + + addSlowPathGenerator( + slowPathCall(slowPath, this, operationAllocatePropertyStorageWithInitialCapacity, scratchGPR)); + + m_jit.storePtr(scratchGPR, JITCompiler::Address(baseGPR, JSObject::offsetOfOutOfLineStorage())); + + storageResult(scratchGPR, m_compileIndex); +} + +void SpeculativeJIT::compileReallocatePropertyStorage(Node& node) +{ + SpeculateCellOperand base(this, node.child1()); + StorageOperand oldStorage(this, node.child2()); + GPRTemporary scratch1(this); + GPRTemporary scratch2(this); + + GPRReg baseGPR = base.gpr(); + GPRReg oldStorageGPR = oldStorage.gpr(); + GPRReg scratchGPR1 = scratch1.gpr(); + GPRReg scratchGPR2 = scratch2.gpr(); + + JITCompiler::Jump slowPath; + + size_t oldSize = node.structureTransitionData().previousStructure->outOfLineCapacity() * sizeof(JSValue); + size_t newSize = oldSize * outOfLineGrowthFactor; + ASSERT(newSize == node.structureTransitionData().newStructure->outOfLineCapacity() * sizeof(JSValue)); + CopiedAllocator* copiedAllocator = &m_jit.globalData()->heap.storageAllocator(); + + m_jit.loadPtr(&copiedAllocator->m_currentRemaining, scratchGPR2); + slowPath = m_jit.branchSubPtr(JITCompiler::Signed, JITCompiler::TrustedImm32(newSize), scratchGPR2); + 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); + + 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)); + } + m_jit.storePtr(scratchGPR2, JITCompiler::Address(baseGPR, JSObject::offsetOfOutOfLineStorage())); + + storageResult(scratchGPR2, m_compileIndex); +} + } } // namespace JSC::DFG #endif diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h index 487addd7f..cb7d89106 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h @@ -1151,6 +1151,16 @@ public: // machine registers, and delegate the calling convention specific // decision as to how to fill the regsiters to setupArguments* methods. #if USE(JSVALUE64) + JITCompiler::Call callOperation(P_DFGOperation_E operation, GPRReg result) + { + m_jit.setupArgumentsExecState(); + return appendCallWithExceptionCheckSetResult(operation, result); + } + JITCompiler::Call callOperation(P_DFGOperation_ES operation, GPRReg result, size_t size) + { + m_jit.setupArgumentsWithExecState(TrustedImmPtr(size)); + return appendCallWithExceptionCheckSetResult(operation, result); + } JITCompiler::Call callOperation(J_DFGOperation_E operation, GPRReg result) { m_jit.setupArgumentsExecState(); @@ -1413,6 +1423,16 @@ public: #define EABI_32BIT_DUMMY_ARG #endif + JITCompiler::Call callOperation(P_DFGOperation_E operation, GPRReg result) + { + m_jit.setupArgumentsExecState(); + return appendCallWithExceptionCheckSetResult(operation, result); + } + JITCompiler::Call callOperation(P_DFGOperation_ES operation, GPRReg result, size_t size) + { + m_jit.setupArgumentsWithExecState(TrustedImmPtr(size)); + return appendCallWithExceptionCheckSetResult(operation, result); + } JITCompiler::Call callOperation(Z_DFGOperation_D operation, GPRReg result, FPRReg arg1) { prepareForExternalCall(); @@ -2048,6 +2068,9 @@ public: bool compileStrictEq(Node&); + void compileAllocatePropertyStorage(Node&); + void compileReallocatePropertyStorage(Node&); + void compileGetCharCodeAt(Node&); void compileGetByValOnString(Node&); diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp index ed98e0800..c63ba8c21 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp @@ -1918,7 +1918,7 @@ void SpeculativeJIT::compile(Node& node) break; } - if (isArraySpeculation(value.m_type)) { + if (isArraySpeculation(value.m_type) || isCellSpeculation(value.m_type)) { GPRTemporary result(this); m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr()); @@ -2010,7 +2010,7 @@ void SpeculativeJIT::compile(Node& node) // OSR exit, would not be visible to the old JIT in any way. m_codeOriginForOSR = nextNode->codeOrigin; - if (!node.variableAccessData()->isCaptured()) { + if (!node.variableAccessData()->isCaptured() && !m_jit.graph().isCreatedThisArgument(node.local())) { if (node.variableAccessData()->shouldUseDoubleFormat()) { SpeculateDoubleOperand value(this, node.child1()); m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node.local())); @@ -2046,6 +2046,14 @@ void SpeculativeJIT::compile(Node& node) recordSetLocal(node.local(), ValueSource(CellInRegisterFile)); break; } + if (isCellSpeculation(predictedType)) { + SpeculateCellOperand cell(this, node.child1()); + GPRReg cellGPR = cell.gpr(); + m_jit.storePtr(cellGPR, JITCompiler::payloadFor(node.local())); + noResult(m_compileIndex); + recordSetLocal(node.local(), ValueSource(CellInRegisterFile)); + break; + } if (isBooleanSpeculation(predictedType)) { SpeculateBooleanOperand value(this, node.child1()); m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local())); @@ -3542,6 +3550,14 @@ void SpeculativeJIT::compile(Node& node) break; } + case AllocatePropertyStorage: + compileAllocatePropertyStorage(node); + break; + + case ReallocatePropertyStorage: + compileReallocatePropertyStorage(node); + break; + case GetPropertyStorage: { SpeculateCellOperand base(this, node.child1()); GPRTemporary result(this, base); diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp index 9e468e758..6dbb8a4b1 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp @@ -2052,7 +2052,7 @@ void SpeculativeJIT::compile(Node& node) // OSR exit, would not be visible to the old JIT in any way. m_codeOriginForOSR = nextNode->codeOrigin; - if (!node.variableAccessData()->isCaptured()) { + if (!node.variableAccessData()->isCaptured() && !m_jit.graph().isCreatedThisArgument(node.local())) { if (node.variableAccessData()->shouldUseDoubleFormat()) { SpeculateDoubleOperand value(this, node.child1()); m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node.local())); @@ -2082,6 +2082,14 @@ void SpeculativeJIT::compile(Node& node) recordSetLocal(node.local(), ValueSource(CellInRegisterFile)); break; } + if (isCellSpeculation(predictedType)) { + SpeculateCellOperand cell(this, node.child1()); + GPRReg cellGPR = cell.gpr(); + m_jit.storePtr(cellGPR, JITCompiler::addressFor(node.local())); + noResult(m_compileIndex); + recordSetLocal(node.local(), ValueSource(CellInRegisterFile)); + break; + } if (isBooleanSpeculation(predictedType)) { SpeculateBooleanOperand boolean(this, node.child1()); m_jit.storePtr(boolean.gpr(), JITCompiler::addressFor(node.local())); @@ -3557,6 +3565,14 @@ void SpeculativeJIT::compile(Node& node) break; } + case AllocatePropertyStorage: + compileAllocatePropertyStorage(node); + break; + + case ReallocatePropertyStorage: + compileReallocatePropertyStorage(node); + break; + case GetPropertyStorage: { SpeculateCellOperand base(this, node.child1()); GPRTemporary result(this, base); diff --git a/Source/JavaScriptCore/dfg/DFGValueSource.h b/Source/JavaScriptCore/dfg/DFGValueSource.h index be4a6e081..f776137d0 100644 --- a/Source/JavaScriptCore/dfg/DFGValueSource.h +++ b/Source/JavaScriptCore/dfg/DFGValueSource.h @@ -130,7 +130,7 @@ public: { if (isInt32Speculation(prediction)) return ValueSource(Int32InRegisterFile); - if (isArraySpeculation(prediction)) + if (isArraySpeculation(prediction) || isCellSpeculation(prediction)) return ValueSource(CellInRegisterFile); if (isBooleanSpeculation(prediction)) return ValueSource(BooleanInRegisterFile); diff --git a/Source/JavaScriptCore/heap/JITStubRoutineSet.h b/Source/JavaScriptCore/heap/JITStubRoutineSet.h index ea120132e..cb76ac8bd 100644 --- a/Source/JavaScriptCore/heap/JITStubRoutineSet.h +++ b/Source/JavaScriptCore/heap/JITStubRoutineSet.h @@ -28,8 +28,6 @@ #include <wtf/Platform.h> -#if ENABLE(JIT) - #include "JITStubRoutine.h" #include <wtf/FastAllocBase.h> #include <wtf/HashMap.h> @@ -40,6 +38,8 @@ namespace JSC { class GCAwareJITStubRoutine; class SlotVisitor; +#if ENABLE(JIT) + class JITStubRoutineSet { WTF_MAKE_NONCOPYABLE(JITStubRoutineSet); WTF_MAKE_FAST_ALLOCATED; @@ -72,9 +72,26 @@ private: Vector<GCAwareJITStubRoutine*> m_listOfRoutines; }; -} // namespace JSC +#else // !ENABLE(JIT) -#endif // ENABLE(JIT) +class JITStubRoutineSet { + WTF_MAKE_NONCOPYABLE(JITStubRoutineSet); + WTF_MAKE_FAST_ALLOCATED; + +public: + JITStubRoutineSet() { } + ~JITStubRoutineSet() { } + + void add(GCAwareJITStubRoutine*) { } + void clearMarks() { } + void mark(void*) { } + void deleteUnmarkedJettisonedStubRoutines() { } + void traceMarkedStubRoutines(SlotVisitor&) { } +}; + +#endif // !ENABLE(JIT) + +} // namespace JSC #endif // JITStubRoutineSet_h 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/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp index b6072a5d6..3edb8589e 100644 --- a/Source/JavaScriptCore/interpreter/Interpreter.cpp +++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp @@ -77,6 +77,8 @@ using namespace std; namespace JSC { +static CallFrame* getCallerInfo(JSGlobalData*, CallFrame*, int& lineNumber, unsigned& bytecodeOffset); + // Returns the depth of the scope chain within a given call frame. static int depth(CodeBlock* codeBlock, ScopeChainNode* sc) { @@ -606,7 +608,13 @@ void Interpreter::initialize(LLInt::Data* llintData, bool canUseJIT) #endif } -#ifndef NDEBUG +#ifdef NDEBUG + +void Interpreter::dumpCallFrame(CallFrame*) +{ +} + +#else void Interpreter::dumpCallFrame(CallFrame* callFrame) { @@ -624,34 +632,42 @@ void Interpreter::dumpRegisters(CallFrame* callFrame) CodeBlock* codeBlock = callFrame->codeBlock(); const Register* it; const Register* end; - JSValue v; - it = callFrame->registers() - RegisterFile::CallFrameHeaderSize - codeBlock->numParameters(); - v = (*it).jsValue(); -#if USE(JSVALUE32_64) - dataLog("[this] | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v)); ++it; -#else - dataLog("[this] | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v)); ++it; -#endif - end = it + max(codeBlock->numParameters() - 1, 0); // - 1 to skip "this" - if (it != end) { - do { - v = (*it).jsValue(); + it = callFrame->registers() - RegisterFile::CallFrameHeaderSize - callFrame->argumentCountIncludingThis(); + end = callFrame->registers() - RegisterFile::CallFrameHeaderSize; + while (it < end) { + JSValue v = it->jsValue(); + int registerNumber = it - callFrame->registers(); + UString name = codeBlock->nameForRegister(registerNumber); #if USE(JSVALUE32_64) - dataLog("[param] | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v)); + dataLog("[r% 3d %14s] | %10p | %-16s 0x%llx \n", registerNumber, name.ascii().data(), it, v.description(), JSValue::encode(v)); #else - dataLog("[param] | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v)); + dataLog("[r% 3d %14s] | %10p | %-16s %p \n", registerNumber, name.ascii().data(), it, v.description(), JSValue::encode(v)); #endif - ++it; - } while (it != end); + it++; } + dataLog("-----------------------------------------------------------------------------\n"); - dataLog("[CodeBlock] | %10p | %p \n", it, (*it).codeBlock()); ++it; - dataLog("[ScopeChain] | %10p | %p \n", it, (*it).scopeChain()); ++it; - dataLog("[CallerRegisters] | %10p | %d \n", it, (*it).i()); ++it; - dataLog("[ReturnPC] | %10p | %p \n", it, (*it).vPC()); ++it; - dataLog("[ArgumentCount] | %10p | %d \n", it, (*it).i()); ++it; - dataLog("[Callee] | %10p | %p \n", it, (*it).function()); ++it; + dataLog("[ArgumentCount] | %10p | %lu \n", it, (unsigned long) callFrame->argumentCount()); + ++it; + dataLog("[CallerFrame] | %10p | %p \n", it, callFrame->callerFrame()); + ++it; + dataLog("[Callee] | %10p | %p \n", it, callFrame->callee()); + ++it; + dataLog("[ScopeChain] | %10p | %p \n", it, callFrame->scopeChain()); + ++it; +#if ENABLE(JIT) + AbstractPC pc = callFrame->abstractReturnPC(callFrame->globalData()); + if (pc.hasJITReturnAddress()) + dataLog("[ReturnJITPC] | %10p | %p \n", it, pc.jitReturnAddress().value()); +#endif + unsigned bytecodeOffset = 0; + int line = 0; + getCallerInfo(&callFrame->globalData(), callFrame, line, bytecodeOffset); + dataLog("[ReturnVPC] | %10p | %d (line %d)\n", it, bytecodeOffset, line); + ++it; + dataLog("[CodeBlock] | %10p | %p \n", it, callFrame->codeBlock()); + ++it; dataLog("-----------------------------------------------------------------------------\n"); int registerCount = 0; @@ -659,11 +675,13 @@ void Interpreter::dumpRegisters(CallFrame* callFrame) end = it + codeBlock->m_numVars; if (it != end) { do { - v = (*it).jsValue(); + JSValue v = it->jsValue(); + int registerNumber = it - callFrame->registers(); + UString name = codeBlock->nameForRegister(registerNumber); #if USE(JSVALUE32_64) - dataLog("[r%2d] | %10p | %-16s 0x%llx \n", registerCount, it, v.description(), JSValue::encode(v)); + dataLog("[r% 3d %14s] | %10p | %-16s 0x%llx \n", registerNumber, name.ascii().data(), it, v.description(), JSValue::encode(v)); #else - dataLog("[r%2d] | %10p | %-16s %p \n", registerCount, it, v.description(), JSValue::encode(v)); + dataLog("[r% 3d %14s] | %10p | %-16s %p \n", registerNumber, name.ascii().data(), it, v.description(), JSValue::encode(v)); #endif ++it; ++registerCount; @@ -674,11 +692,11 @@ void Interpreter::dumpRegisters(CallFrame* callFrame) end = it + codeBlock->m_numCalleeRegisters - codeBlock->m_numVars; if (it != end) { do { - v = (*it).jsValue(); + JSValue v = (*it).jsValue(); #if USE(JSVALUE32_64) - dataLog("[r%2d] | %10p | %-16s 0x%llx \n", registerCount, it, v.description(), JSValue::encode(v)); + dataLog("[r% 3d] | %10p | %-16s 0x%llx \n", registerCount, it, v.description(), JSValue::encode(v)); #else - dataLog("[r%2d] | %10p | %-16s %p \n", registerCount, it, v.description(), JSValue::encode(v)); + dataLog("[r% 3d] | %10p | %-16s %p \n", registerCount, it, v.description(), JSValue::encode(v)); #endif ++it; ++registerCount; @@ -838,10 +856,10 @@ static int getLineNumberForCallFrame(JSGlobalData* globalData, CallFrame* callFr #endif } -static CallFrame* getCallerInfo(JSGlobalData* globalData, CallFrame* callFrame, int& lineNumber) +static CallFrame* getCallerInfo(JSGlobalData* globalData, CallFrame* callFrame, int& lineNumber, unsigned& bytecodeOffset) { UNUSED_PARAM(globalData); - unsigned bytecodeOffset = 0; + bytecodeOffset = 0; lineNumber = -1; ASSERT(!callFrame->hasHostCallFrameFlag()); CallFrame* callerFrame = callFrame->codeBlock() ? callFrame->trueCallerFrame() : callFrame->callerFrame()->removeHostCallFrameFlag(); @@ -973,7 +991,8 @@ void Interpreter::getStackTrace(JSGlobalData* globalData, Vector<StackFrame>& re StackFrame s = { Strong<JSObject>(*globalData, callFrame->callee()), StackFrameNativeCode, Strong<ExecutableBase>(), -1, UString()}; results.append(s); } - callFrame = getCallerInfo(globalData, callFrame, line); + unsigned unusedBytecodeOffset = 0; + callFrame = getCallerInfo(globalData, callFrame, line, unusedBytecodeOffset); } } @@ -5330,7 +5349,8 @@ JSValue Interpreter::retrieveCallerFromVMCode(CallFrame* callFrame, JSFunction* return jsNull(); int lineNumber; - CallFrame* callerFrame = getCallerInfo(&callFrame->globalData(), functionCallFrame, lineNumber); + unsigned bytecodeOffset; + CallFrame* callerFrame = getCallerInfo(&callFrame->globalData(), functionCallFrame, lineNumber, bytecodeOffset); if (!callerFrame) return jsNull(); JSValue caller = callerFrame->callee(); @@ -5340,7 +5360,7 @@ JSValue Interpreter::retrieveCallerFromVMCode(CallFrame* callFrame, JSFunction* // Skip over function bindings. ASSERT(caller.isObject()); while (asObject(caller)->inherits(&JSBoundFunction::s_info)) { - callerFrame = getCallerInfo(&callFrame->globalData(), callerFrame, lineNumber); + callerFrame = getCallerInfo(&callFrame->globalData(), callerFrame, lineNumber, bytecodeOffset); if (!callerFrame) return jsNull(); caller = callerFrame->callee(); diff --git a/Source/JavaScriptCore/interpreter/Interpreter.h b/Source/JavaScriptCore/interpreter/Interpreter.h index ba2f4fac4..8663bf8ec 100644 --- a/Source/JavaScriptCore/interpreter/Interpreter.h +++ b/Source/JavaScriptCore/interpreter/Interpreter.h @@ -248,6 +248,9 @@ namespace JSC { void dumpSampleData(ExecState* exec); void startSampling(); void stopSampling(); + + JS_EXPORT_PRIVATE void dumpCallFrame(CallFrame*); + private: enum ExecutionFlag { Normal, InitializeAndReturn }; @@ -279,7 +282,6 @@ namespace JSC { JSValue privateExecute(ExecutionFlag, RegisterFile*, CallFrame*); - void dumpCallFrame(CallFrame*); void dumpRegisters(CallFrame*); bool isCallBytecode(Opcode opcode) { return opcode == getOpcode(op_call) || opcode == getOpcode(op_construct) || opcode == getOpcode(op_call_eval); } diff --git a/Source/JavaScriptCore/jsc.cpp b/Source/JavaScriptCore/jsc.cpp index 5f3dbdb99..00ad5d3b2 100644 --- a/Source/JavaScriptCore/jsc.cpp +++ b/Source/JavaScriptCore/jsc.cpp @@ -88,6 +88,7 @@ static EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState*); static EncodedJSValue JSC_HOST_CALL functionGC(ExecState*); #ifndef NDEBUG static EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState*); +static EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState*); #endif static EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*); static EncodedJSValue JSC_HOST_CALL functionRun(ExecState*); @@ -194,6 +195,7 @@ protected: addFunction(globalData, "quit", functionQuit, 0); addFunction(globalData, "gc", functionGC, 0); #ifndef NDEBUG + addFunction(globalData, "dumpCallFrame", functionDumpCallFrame, 0); addFunction(globalData, "releaseExecutableMemory", functionReleaseExecutableMemory, 0); #endif addFunction(globalData, "version", functionVersion, 1); @@ -281,6 +283,15 @@ EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec) return JSValue::encode(jsUndefined()); } +#ifndef NDEBUG +EncodedJSValue JSC_HOST_CALL functionDumpCallFrame(ExecState* exec) +{ + if (!exec->callerFrame()->hasHostCallFrameFlag()) + exec->globalData().interpreter->dumpCallFrame(exec->callerFrame()); + return JSValue::encode(jsUndefined()); +} +#endif + EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec) { fprintf(stderr, "--> %s\n", exec->argument(0).toString(exec)->value(exec).utf8().data()); diff --git a/Source/JavaScriptCore/offlineasm/armv7.rb b/Source/JavaScriptCore/offlineasm/armv7.rb index 18538120b..6595fdc71 100644 --- a/Source/JavaScriptCore/offlineasm/armv7.rb +++ b/Source/JavaScriptCore/offlineasm/armv7.rb @@ -743,8 +743,8 @@ end class Instruction def lowerARMv7 - $asm.codeOrigin codeOriginString - $asm.annotation annotation + $asm.codeOrigin codeOriginString if $enableCodeOriginComments + $asm.annotation annotation if $enableInstrAnnotations case opcode when "addi", "addp", "addis" @@ -1012,7 +1012,7 @@ class Instruction raise "Wrong number of arguments to smull in #{self.inspect} at #{codeOriginString}" unless operands.length == 4 $asm.puts "smull #{operands[2].armV7Operand}, #{operands[3].armV7Operand}, #{operands[0].armV7Operand}, #{operands[1].armV7Operand}" else - raise "Unhandled opcode #{opcode} at #{codeOriginString}" + lowerDefault end end end diff --git a/Source/JavaScriptCore/offlineasm/asm.rb b/Source/JavaScriptCore/offlineasm/asm.rb index 0cf6320af..1603f4af4 100644 --- a/Source/JavaScriptCore/offlineasm/asm.rb +++ b/Source/JavaScriptCore/offlineasm/asm.rb @@ -45,6 +45,8 @@ class Assembler @codeOrigin = nil @numLocalLabels = 0 @numGlobalLabels = 0 + + @newlineSpacerState = :none end def enterAsm @@ -66,33 +68,60 @@ class Assembler # Concatenates all the various components of the comment to dump. def lastComment + separator = " " result = "" - result = " #{@comment} ." if @comment - result += " #{@annotation} ." if @annotation and $enableTrailingInstrAnnotations - result += " #{@internalComment} ." if @internalComment - result += " #{@codeOrigin} ." if @codeOrigin and $enableCodeOriginComments + result = "#{@comment}" if @comment + if @annotation and $enableInstrAnnotations + result += separator if result != "" + result += "#{@annotation}" + end + if @internalComment + result += separator if result != "" + result += "#{@internalComment}" + end + if @codeOrigin and $enableCodeOriginComments + result += separator if result != "" + result += "#{@codeOrigin}" + end if result != "" - result = " //" + result + result = "// " + result end # Reset all the components that we've just sent to be dumped. @commentState = :none @comment = nil - @internalComment = nil @annotation = nil @codeOrigin = nil + @internalComment = nil result end - # Dumps the current instruction annotation in interlaced mode if appropriate. - def putInterlacedAnnotation() + def formatDump(dumpStr, comment, commentColumns=$preferredCommentStartColumn) + if comment.length > 0 + "%-#{commentColumns}s %s" % [dumpStr, comment] + else + dumpStr + end + end + + # private method for internal use only. + def putAnnotation(text) raise unless @state == :asm - if $enableInterlacedInstrAnnotations - @outp.puts(" // #{@annotation}") if @annotation + if $enableInstrAnnotations + @outp.puts text @annotation = nil end end + def putLocalAnnotation() + putAnnotation " // #{@annotation}" if @annotation + end + + def putGlobalAnnotation() + putsNewlineSpacerIfAppropriate(:annotation) + putAnnotation "// #{@annotation}" if @annotation + end + def putsLastComment comment = lastComment unless comment.empty? @@ -102,8 +131,7 @@ class Assembler def puts(*line) raise unless @state == :asm - putInterlacedAnnotation - @outp.puts(" \"\\t" + line.join('') + "\\n\"#{lastComment}") + @outp.puts(formatDump(" \"\\t" + line.join('') + "\\n\"", lastComment)) end def print(line) @@ -111,12 +139,20 @@ class Assembler @outp.print("\"" + line + "\"") end + def putsNewlineSpacerIfAppropriate(state) + if @newlineSpacerState != state + @outp.puts("\n") + @newlineSpacerState = state + end + end + def putsLabel(labelName) raise unless @state == :asm @numGlobalLabels += 1 - @outp.puts("\n") + putsNewlineSpacerIfAppropriate(:global) @internalComment = $enableLabelCountComments ? "Global Label #{@numGlobalLabels}" : nil - @outp.puts("OFFLINE_ASM_GLOBAL_LABEL(#{labelName})#{lastComment}") + @outp.puts(formatDump("OFFLINE_ASM_GLOBAL_LABEL(#{labelName})", lastComment)) + @newlineSpacerState = :none # After a global label, we can use another spacer. end def putsLocalLabel(labelName) @@ -124,7 +160,7 @@ class Assembler @numLocalLabels += 1 @outp.puts("\n") @internalComment = $enableLabelCountComments ? "Local Label #{@numLocalLabels}" : nil - @outp.puts("OFFLINE_ASM_LOCAL_LABEL(#{labelName})#{lastComment}") + @outp.puts(formatDump(" OFFLINE_ASM_LOCAL_LABEL(#{labelName})", lastComment)) end def self.labelReference(labelName) diff --git a/Source/JavaScriptCore/offlineasm/ast.rb b/Source/JavaScriptCore/offlineasm/ast.rb index 86ad6bcb2..9333247dc 100644 --- a/Source/JavaScriptCore/offlineasm/ast.rb +++ b/Source/JavaScriptCore/offlineasm/ast.rb @@ -806,6 +806,17 @@ class Instruction < Node def dump "\t" + opcode.to_s + " " + operands.collect{|v| v.dump}.join(", ") end + + def lowerDefault + case opcode + when "localAnnotation" + $asm.putLocalAnnotation + when "globalAnnotation" + $asm.putGlobalAnnotation + else + raise "Unhandled opcode #{opcode} at #{codeOriginString}" + end + end end class Error < NoChildren @@ -1180,7 +1191,7 @@ end class Macro < Node attr_reader :name, :variables, :body - + def initialize(codeOrigin, name, variables, body) super(codeOrigin) @name = name @@ -1202,14 +1213,15 @@ class Macro < Node end class MacroCall < Node - attr_reader :name, :operands + attr_reader :name, :operands, :annotation - def initialize(codeOrigin, name, operands) + def initialize(codeOrigin, name, operands, annotation) super(codeOrigin) @name = name @operands = operands raise unless @operands @operands.each{|v| raise unless v} + @annotation = annotation end def children @@ -1217,7 +1229,7 @@ class MacroCall < Node end def mapChildren(&proc) - MacroCall.new(codeOrigin, @name, @operands.map(&proc)) + MacroCall.new(codeOrigin, @name, @operands.map(&proc), @annotation) end def dump diff --git a/Source/JavaScriptCore/offlineasm/config.rb b/Source/JavaScriptCore/offlineasm/config.rb index ce1898170..e6287f367 100644 --- a/Source/JavaScriptCore/offlineasm/config.rb +++ b/Source/JavaScriptCore/offlineasm/config.rb @@ -21,6 +21,8 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF # THE POSSIBILITY OF SUCH DAMAGE. +$preferredCommentStartColumn = 70 + # Turns on dumping of the count of labels. # For example, the output will look like this: @@ -45,32 +47,11 @@ $enableCodeOriginComments = true # Turns on recording and dumping of annotations in the generated output file. # An annotations can be specified for each instruction in the source asm files. -# -# $enableInterlacedInstrAnnotations will interlace the annotation between -# instructions. For example, the output will look like this: +# For example, the output will look like this: # # ... -# // @ t2<CodeBlock> = cfr.CodeBlock -# "\tmovq -8(%r13), %rcx\n" -# // @ t2<size_t> = t2<CodeBlock>.m_numVars -# "\tmovl 52(%rcx), %ecx\n" +# "\tmovq -8(%r13), %rcx\n" // t2<CodeBlock> = cfr.CodeBlock +# "\tmovl 52(%rcx), %ecx\n" // t2<size_t> = t2<CodeBlock>.m_numVars # ... # -# $enableTrailingInstrAnnotations will insert the annotation in the trailing -# comment after your instructions. For example, the output will look like this: -# -# ... -# "\tmovq -8(%r13), %rcx\n" // @ t2<CodeBlock> = cfr.CodeBlock -# "\tmovl 52(%rcx), %ecx\n" // @ t2<size_t> = t2<CodeBlock>.m_numVars -# ... -# -# If both $enableInterlacedInstrAnnotations and $enableTrailingInstrAnnotations -# are enabled, interlaced annotations will take precedence, and any available -# annotations will only be dumped in the interlaced format. -# -$enableInterlacedInstrAnnotations = false -$enableTrailingInstrAnnotations = false - - -# Sanity check for annotation configs. -$enableInstrAnnotations = ($enableInterlacedInstrAnnotations or $enableTrailingInstrAnnotations) +$enableInstrAnnotations = false diff --git a/Source/JavaScriptCore/offlineasm/parser.rb b/Source/JavaScriptCore/offlineasm/parser.rb index 8696a61a9..70b03cf70 100644 --- a/Source/JavaScriptCore/offlineasm/parser.rb +++ b/Source/JavaScriptCore/offlineasm/parser.rb @@ -74,6 +74,15 @@ class Token end end +class Annotation + attr_reader :codeOrigin, :type, :string + def initialize(codeOrigin, type, string) + @codeOrigin = codeOrigin + @type = type + @string = string + end +end + # # The lexer. Takes a string and returns an array of tokens. # @@ -83,17 +92,20 @@ def lex(str, fileName) result = [] lineNumber = 1 annotation = nil + whitespaceFound = false while not str.empty? case str when /\A\#([^\n]*)/ # comment, ignore - when /\A\/\/([^\n]*)/ + when /\A\/\/\ ?([^\n]*)/ # annotation annotation = $1 + annotationType = whitespaceFound ? :local : :global when /\A\n/ # We've found a '\n'. Emit the last comment recorded if appropriate: if $enableInstrAnnotations and annotation - result << Token.new(CodeOrigin.new(fileName, lineNumber), "@" + annotation) + result << Annotation.new(CodeOrigin.new(fileName, lineNumber), + annotationType, annotation) annotation = nil end result << Token.new(CodeOrigin.new(fileName, lineNumber), $&) @@ -106,6 +118,9 @@ def lex(str, fileName) result << Token.new(CodeOrigin.new(fileName, lineNumber), $&) when /\A([ \t]+)/ # whitespace, ignore + whitespaceFound = true + str = $~.post_match + next when /\A0x([0-9a-fA-F]+)/ result << Token.new(CodeOrigin.new(fileName, lineNumber), $&.hex.to_s) when /\A0([0-7]+)/ @@ -119,6 +134,7 @@ def lex(str, fileName) else raise "Lexer error at #{CodeOrigin.new(fileName, lineNumber).to_s}, unexpected sequence #{str[0..20].inspect}" end + whitespaceFound = false str = $~.post_match end result @@ -146,10 +162,6 @@ def isIdentifier(token) token =~ /\A[a-zA-Z]([a-zA-Z0-9_]*)\Z/ and not isKeyword(token) end -def isAnnotation(token) - token =~ /\A\@([^\n]*)/ -end - def isLabel(token) token =~ /\A_([a-zA-Z0-9_]*)\Z/ end @@ -175,6 +187,7 @@ class Parser def initialize(data, fileName) @tokens = lex(data, fileName) @idx = 0 + @annotation = nil end def parseError(*comment) @@ -487,6 +500,20 @@ class Parser loop { if (@idx == @tokens.length and not final) or (final and @tokens[@idx] =~ final) break + elsif @tokens[@idx].is_a? Annotation + # This is the only place where we can encounter a global + # annotation, and hence need to be able to distinguish between + # them. + # globalAnnotations are the ones that start from column 0. All + # others are considered localAnnotations. The only reason to + # distinguish between them is so that we can format the output + # nicely as one would expect. + + codeOrigin = @tokens[@idx].codeOrigin + annotationOpcode = (@tokens[@idx].type == :global) ? "globalAnnotation" : "localAnnotation" + list << Instruction.new(codeOrigin, annotationOpcode, [], @tokens[@idx].string) + @annotation = nil + @idx += 2 # Consume the newline as well. elsif @tokens[@idx] == "\n" # ignore @idx += 1 @@ -547,21 +574,22 @@ class Parser @idx += 1 if (not final and @idx == @tokens.size) or (final and @tokens[@idx] =~ final) # Zero operand instruction, and it's the last one. - list << Instruction.new(codeOrigin, name, []) + list << Instruction.new(codeOrigin, name, [], @annotation) + @annotation = nil break - elsif isAnnotation @tokens[@idx] - annotation = @tokens[@idx].string - list << Instruction.new(codeOrigin, name, [], annotation) + elsif @tokens[@idx].is_a? Annotation + list << Instruction.new(codeOrigin, name, [], @tokens[@idx].string) + @annotation = nil @idx += 2 # Consume the newline as well. elsif @tokens[@idx] == "\n" # Zero operand instruction. - list << Instruction.new(codeOrigin, name, []) + list << Instruction.new(codeOrigin, name, [], @annotation) + @annotation = nil @idx += 1 else # It's definitely an instruction, and it has at least one operand. operands = [] endOfSequence = false - annotation = nil loop { operands << parseOperand("while inside of instruction #{name}") if (not final and @idx == @tokens.size) or (final and @tokens[@idx] =~ final) @@ -571,8 +599,8 @@ class Parser elsif @tokens[@idx] == "," # Has another operand. @idx += 1 - elsif isAnnotation @tokens[@idx] - annotation = @tokens[@idx].string + elsif @tokens[@idx].is_a? Annotation + @annotation = @tokens[@idx].string @idx += 2 # Consume the newline as well. break elsif @tokens[@idx] == "\n" @@ -583,11 +611,14 @@ class Parser parseError("Expected a comma, newline, or #{final} after #{operands.last.dump}") end } - list << Instruction.new(codeOrigin, name, operands, annotation) + list << Instruction.new(codeOrigin, name, operands, @annotation) + @annotation = nil if endOfSequence break end end + + # Check for potential macro invocation: elsif isIdentifier @tokens[@idx] codeOrigin = @tokens[@idx].codeOrigin name = @tokens[@idx].string @@ -624,7 +655,13 @@ class Parser end } end - list << MacroCall.new(codeOrigin, name, operands) + # Check if there's a trailing annotation after the macro invoke: + if @tokens[@idx].is_a? Annotation + @annotation = @tokens[@idx].string + @idx += 2 # Consume the newline as well. + end + list << MacroCall.new(codeOrigin, name, operands, @annotation) + @annotation = nil else parseError "Expected \"(\" after #{name}" end diff --git a/Source/JavaScriptCore/offlineasm/transform.rb b/Source/JavaScriptCore/offlineasm/transform.rb index a47ea0ad6..c838629f0 100644 --- a/Source/JavaScriptCore/offlineasm/transform.rb +++ b/Source/JavaScriptCore/offlineasm/transform.rb @@ -229,6 +229,9 @@ class Sequence mapping[myMacros[item.name].variables[idx]] = item.operands[idx] end } + if item.annotation + newList << Instruction.new(item.codeOrigin, "localAnnotation", [], item.annotation) + end newList += myMacros[item.name].body.substitute(mapping).demacroify(myMyMacros).renameLabels(item.name).list else newList << item.demacroify(myMacros) diff --git a/Source/JavaScriptCore/offlineasm/x86.rb b/Source/JavaScriptCore/offlineasm/x86.rb index 470318a09..cebc83326 100644 --- a/Source/JavaScriptCore/offlineasm/x86.rb +++ b/Source/JavaScriptCore/offlineasm/x86.rb @@ -624,8 +624,8 @@ class Instruction end def lowerX86Common - $asm.codeOrigin codeOriginString - $asm.annotation annotation + $asm.codeOrigin codeOriginString if $enableCodeOriginComments + $asm.annotation annotation if $enableInstrAnnotations case opcode when "addi" @@ -1028,7 +1028,7 @@ class Instruction when "leap" $asm.puts "lea#{x86Suffix(:ptr)} #{operands[0].x86AddressOperand(:ptr)}, #{operands[1].x86Operand(:ptr)}" else - raise "Bad opcode: #{opcode}" + lowerDefault end end end diff --git a/Source/JavaScriptCore/runtime/DatePrototype.cpp b/Source/JavaScriptCore/runtime/DatePrototype.cpp index f81ae10f3..d3d0fe574 100644 --- a/Source/JavaScriptCore/runtime/DatePrototype.cpp +++ b/Source/JavaScriptCore/runtime/DatePrototype.cpp @@ -66,10 +66,6 @@ #include <unicode/udat.h> #endif -#if OS(WINCE) && !PLATFORM(QT) -extern "C" size_t strftime(char * const s, const size_t maxsize, const char * const format, const struct tm * const t); //provided by libce -#endif - using namespace WTF; namespace JSC { @@ -223,22 +219,57 @@ static JSCell* formatLocaleDate(ExecState* exec, DateInstance* dateObject, doubl static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, LocaleDateTimeFormat format) { +#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; + + Vector<UChar, 128> buffer; + size_t length = 0; + + if (format == LocaleDate) { + buffer.resize(GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &systemTime, 0, 0, 0)); + length = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &systemTime, 0, buffer.data(), buffer.size()); + } else if (format == LocaleTime) { + buffer.resize(GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &systemTime, 0, 0, 0)); + length = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &systemTime, 0, buffer.data(), buffer.size()); + } else if (format == LocaleDateAndTime) { + buffer.resize(GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &systemTime, 0, 0, 0) + GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &systemTime, 0, 0, 0)); + length = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &systemTime, 0, buffer.data(), buffer.size()); + if (length) { + buffer[length - 1] = ' '; + length += GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &systemTime, 0, buffer.data() + length, buffer.size() - length); + } + } else + ASSERT_NOT_REACHED(); + + // Remove terminating null character. + if (length) + length--; + + return jsNontrivialString(exec, UString(buffer.data(), length)); + +#else // OS(WINDOWS) + #if HAVE(LANGINFO_H) static const nl_item formats[] = { D_T_FMT, D_FMT, T_FMT }; -#elif (OS(WINCE) && !PLATFORM(QT)) - // strftime() does not support '#' on WinCE - static const char* const formatStrings[] = { "%c", "%x", "%X" }; #else static const char* const formatStrings[] = { "%#c", "%#x", "%X" }; #endif - + // Offset year if needed struct tm localTM = gdt; int year = gdt.year + 1900; bool yearNeedsOffset = year < 1900 || year > 2038; if (yearNeedsOffset) localTM.tm_year = equivalentYearForDST(year) - 1900; - + #if HAVE(LANGINFO_H) // We do not allow strftime to generate dates with 2-digits years, // both to avoid ambiguity, and a crash in strncpy, for years that @@ -259,19 +290,19 @@ static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, L #else size_t ret = strftime(timebuffer, bufsize, formatStrings[format], &localTM); #endif - + if (ret == 0) return jsEmptyString(exec); - + // Copy original into the buffer if (yearNeedsOffset && format != LocaleTime) { static const int yearLen = 5; // FIXME will be a problem in the year 10,000 char yearString[yearLen]; - + snprintf(yearString, yearLen, "%d", localTM.tm_year + 1900); char* yearLocation = strstr(timebuffer, yearString); snprintf(yearString, yearLen, "%d", year); - + strncpy(yearLocation, yearString, yearLen - 1); } @@ -296,6 +327,7 @@ static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, L #endif return jsNontrivialString(exec, timebuffer); +#endif // OS(WINDOWS) } static JSCell* formatLocaleDate(ExecState* exec, DateInstance* dateObject, double, LocaleDateTimeFormat format) diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.h b/Source/JavaScriptCore/runtime/JSGlobalData.h index 90925778b..59a672f67 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalData.h +++ b/Source/JavaScriptCore/runtime/JSGlobalData.h @@ -129,6 +129,10 @@ namespace JSC { #if ENABLE(DFG_JIT) class ConservativeRoots; +#if COMPILER(MSVC) +#pragma warning(push) +#pragma warning(disable: 4200) // Disable "zero-sized array in struct/union" warning +#endif struct ScratchBuffer { ScratchBuffer() : m_activeLength(0) @@ -151,6 +155,9 @@ namespace JSC { size_t m_activeLength; void* m_buffer[0]; }; +#if COMPILER(MSVC) +#pragma warning(pop) +#endif #endif class JSGlobalData : public ThreadSafeRefCounted<JSGlobalData> { diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp index ccc49fd5c..587929f66 100644 --- a/Source/JavaScriptCore/runtime/JSObject.cpp +++ b/Source/JavaScriptCore/runtime/JSObject.cpp @@ -599,19 +599,13 @@ PropertyStorage JSObject::growOutOfLineStorage(JSGlobalData& globalData, size_t PropertyStorage oldPropertyStorage = m_outOfLineStorage.get(); PropertyStorage newPropertyStorage = 0; - if (!oldPropertyStorage) { - // We have this extra temp here to slake GCC's thirst for the blood of those who dereference type-punned pointers. - void* temp = newPropertyStorage; - if (!globalData.heap.tryAllocateStorage(sizeof(WriteBarrierBase<Unknown>) * newSize, &temp)) - CRASH(); - newPropertyStorage = static_cast<PropertyStorage>(temp); - } else { - // We have this extra temp here to slake GCC's thirst for the blood of those who dereference type-punned pointers. - void* temp = oldPropertyStorage; - if (!globalData.heap.tryReallocateStorage(&temp, sizeof(WriteBarrierBase<Unknown>) * oldSize, sizeof(WriteBarrierBase<Unknown>) * newSize)) - CRASH(); - newPropertyStorage = static_cast<PropertyStorage>(temp); - } + // We have this extra temp here to slake GCC's thirst for the blood of those who dereference type-punned pointers. + void* temp = newPropertyStorage; + if (!globalData.heap.tryAllocateStorage(sizeof(WriteBarrierBase<Unknown>) * newSize, &temp)) + CRASH(); + newPropertyStorage = static_cast<PropertyStorage>(temp); + + memcpy(newPropertyStorage, oldPropertyStorage, sizeof(WriteBarrierBase<Unknown>) * oldSize); ASSERT(newPropertyStorage); return newPropertyStorage; diff --git a/Source/JavaScriptCore/runtime/Structure.cpp b/Source/JavaScriptCore/runtime/Structure.cpp index 509ff3d45..e02105826 100644 --- a/Source/JavaScriptCore/runtime/Structure.cpp +++ b/Source/JavaScriptCore/runtime/Structure.cpp @@ -259,8 +259,8 @@ void Structure::materializePropertyMap(JSGlobalData& globalData) inline size_t nextOutOfLineStorageCapacity(size_t currentCapacity) { if (!currentCapacity) - return 4; - return currentCapacity * 2; + return initialOutOfLineCapacity; + return currentCapacity * outOfLineGrowthFactor; } void Structure::growOutOfLineCapacity() diff --git a/Source/JavaScriptCore/runtime/Structure.h b/Source/JavaScriptCore/runtime/Structure.h index d2d025b98..712ea6bb5 100644 --- a/Source/JavaScriptCore/runtime/Structure.h +++ b/Source/JavaScriptCore/runtime/Structure.h @@ -53,6 +53,15 @@ namespace JSC { class SlotVisitor; class JSString; + // The out-of-line property storage capacity to use when first allocating out-of-line + // storage. Note that all objects start out without having any out-of-line storage; + // this comes into play only on the first property store that exhausts inline storage. + static const unsigned initialOutOfLineCapacity = 4; + + // The factor by which to grow out-of-line storage when it is exhausted, after the + // initial allocation. + static const unsigned outOfLineGrowthFactor = 2; + class Structure : public JSCell { public: friend class StructureTransitionTable; |