diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2012-09-18 15:53:33 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2012-09-18 15:53:33 +0200 |
commit | 6bbb7fbbac94d0f511a7bd0cbd50854ab643bfb2 (patch) | |
tree | d9c68d1cca0b3e352f1e438561f3e504e641a08f /Source/JavaScriptCore | |
parent | d0424a769059c84ae20beb3c217812792ea6726b (diff) | |
download | qtwebkit-6bbb7fbbac94d0f511a7bd0cbd50854ab643bfb2.tar.gz |
Imported WebKit commit c7503cef7ecb236730d1309676ab9fc723fd061d (http://svn.webkit.org/repository/webkit/trunk@128886)
New snapshot with various build fixes
Diffstat (limited to 'Source/JavaScriptCore')
82 files changed, 3388 insertions, 824 deletions
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog index 9e4905f93..76a90cad0 100644 --- a/Source/JavaScriptCore/ChangeLog +++ b/Source/JavaScriptCore/ChangeLog @@ -1,3 +1,978 @@ +2012-09-18 Mark Lam <mark.lam@apple.com> + + Not reviewed. Attempt at greening the WinCairo bot. Touching + LowLevelInterpreter.asm to trigger a rebuild of LLIntDesiredOffsets. + https://bugs.webkit.org/show_bug.cgi?id=96992. + + * llint/LowLevelInterpreter.asm: + +2012-09-18 Peter Gal <galpeter@inf.u-szeged.hu> + + [Qt] REGRESSION(r128790): It broke the ARM build + https://bugs.webkit.org/show_bug.cgi?id=96968 + + Reviewed by Filip Pizlo. + + Implement the missing or32 method in the MacroAssemblerARM.h. + + * assembler/MacroAssemblerARM.h: + (JSC::MacroAssemblerARM::or32): + (MacroAssemblerARM): + +2012-09-18 Mark Lam <mark.lam@apple.com> + + Fix for WinCairo builds. + https://bugs.webkit.org/show_bug.cgi?id=96992. + + Reviewed by Filip Pizlo. + + Adding additional vcproj build targets in LLIntDesiredOffsets.vcproj, + LLIntOffsetsExtractor.vcproj, and LLIntAssembly.vcproj to match those + in jsc.vcproj. + + * JavaScriptCore.vcproj/LLIntAssembly/LLIntAssembly.vcproj: + * JavaScriptCore.vcproj/LLIntDesiredOffsets/LLIntDesiredOffsets.vcproj: + * JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractor.vcproj: + * JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorCommon.vsprops: Added property svn:eol-style. + * JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorDebug.vsprops: Added property svn:eol-style. + * JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorDebugAll.vsprops: Added. + * JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorDebugCairoCFLite.vsprops: Added. + * JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorProduction.vsprops: Added. + * JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorRelease.vsprops: Added property svn:eol-style. + * JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorReleaseCairoCFLite.vsprops: Added. + * JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorReleasePGO.vsprops: Added. + +2012-09-18 Filip Pizlo <fpizlo@apple.com> + + Unreviewed, fix sloppy English in comment. + + * runtime/JSGlobalObject.cpp: + (JSC): + +2012-09-17 Csaba Osztrogonác <ossy@webkit.org> + + Unreviewed, rolling out r128826 and r128813. + + * API/JSCallbackConstructor.cpp: + (JSC): + (JSC::JSCallbackConstructor::JSCallbackConstructor): + * API/JSCallbackConstructor.h: + (JSCallbackConstructor): + * API/JSCallbackObject.cpp: + (JSC): + (JSC::::createStructure): + * API/JSCallbackObject.h: + (JSC::JSCallbackObject::create): + (JSCallbackObject): + * API/JSClassRef.cpp: + (OpaqueJSClass::prototype): + * API/JSObjectRef.cpp: + (JSObjectMake): + (JSObjectGetPrivate): + (JSObjectSetPrivate): + (JSObjectGetPrivateProperty): + (JSObjectSetPrivateProperty): + (JSObjectDeletePrivateProperty): + * API/JSValueRef.cpp: + (JSValueIsObjectOfClass): + * API/JSWeakObjectMapRefPrivate.cpp: + * GNUmakefile.list.am: + * JSCTypedArrayStubs.h: + (JSC): + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * dfg/DFGSpeculativeJIT.h: + (JSC::DFG::SpeculativeJIT::emitAllocateBasicJSObject): + (JSC::DFG::SpeculativeJIT::emitAllocateJSFinalObject): + * heap/Heap.cpp: + (JSC::Heap::isSafeToSweepStructures): + (JSC): + * heap/Heap.h: + (JSC::Heap::allocatorForObjectWithDestructor): + (Heap): + (JSC::Heap::allocateWithDestructor): + (JSC::Heap::allocateStructure): + (JSC): + * heap/IncrementalSweeper.cpp: + (JSC::IncrementalSweeper::IncrementalSweeper): + (JSC::IncrementalSweeper::sweepNextBlock): + (JSC::IncrementalSweeper::startSweeping): + (JSC::IncrementalSweeper::willFinishSweeping): + (JSC::IncrementalSweeper::structuresCanBeSwept): + (JSC): + * heap/IncrementalSweeper.h: + (IncrementalSweeper): + * heap/MarkedAllocator.cpp: + (JSC::MarkedAllocator::tryAllocateHelper): + (JSC::MarkedAllocator::allocateBlock): + * heap/MarkedAllocator.h: + (JSC::MarkedAllocator::cellsNeedDestruction): + (JSC::MarkedAllocator::onlyContainsStructures): + (MarkedAllocator): + (JSC::MarkedAllocator::MarkedAllocator): + (JSC::MarkedAllocator::init): + * heap/MarkedBlock.cpp: + (JSC::MarkedBlock::create): + (JSC::MarkedBlock::MarkedBlock): + (JSC): + (JSC::MarkedBlock::specializedSweep): + (JSC::MarkedBlock::sweep): + (JSC::MarkedBlock::sweepHelper): + * heap/MarkedBlock.h: + (JSC): + (MarkedBlock): + (JSC::MarkedBlock::cellsNeedDestruction): + (JSC::MarkedBlock::onlyContainsStructures): + * heap/MarkedSpace.cpp: + (JSC::MarkedSpace::MarkedSpace): + (JSC::MarkedSpace::resetAllocators): + (JSC::MarkedSpace::canonicalizeCellLivenessData): + (JSC::MarkedSpace::isPagedOut): + (JSC::MarkedSpace::freeBlock): + * heap/MarkedSpace.h: + (MarkedSpace): + (Subspace): + (JSC::MarkedSpace::allocatorFor): + (JSC::MarkedSpace::destructorAllocatorFor): + (JSC::MarkedSpace::allocateWithDestructor): + (JSC::MarkedSpace::allocateStructure): + (JSC::MarkedSpace::forEachBlock): + * heap/SlotVisitor.cpp: + * jit/JIT.h: + * jit/JITInlineMethods.h: + (JSC::JIT::emitAllocateBasicJSObject): + (JSC::JIT::emitAllocateJSFinalObject): + (JSC::JIT::emitAllocateJSArray): + * jsc.cpp: + (GlobalObject::create): + * runtime/Arguments.cpp: + (JSC): + * runtime/Arguments.h: + (Arguments): + (JSC::Arguments::Arguments): + * runtime/ErrorPrototype.cpp: + (JSC): + * runtime/Executable.h: + * runtime/InternalFunction.cpp: + (JSC): + (JSC::InternalFunction::InternalFunction): + * runtime/InternalFunction.h: + (InternalFunction): + * runtime/JSCell.h: + (JSC): + (JSC::allocateCell): + * runtime/JSDestructibleObject.h: Removed. + * runtime/JSGlobalObject.cpp: + (JSC::JSGlobalObject::reset): + (JSC): + * runtime/JSGlobalObject.h: + (JSGlobalObject): + (JSC::JSGlobalObject::createRareDataIfNeeded): + (JSC::JSGlobalObject::create): + * runtime/JSGlobalThis.h: + (JSGlobalThis): + (JSC::JSGlobalThis::JSGlobalThis): + * runtime/JSPropertyNameIterator.h: + * runtime/JSScope.cpp: + (JSC): + * runtime/JSString.h: + (JSC): + * runtime/JSWrapperObject.h: + (JSWrapperObject): + (JSC::JSWrapperObject::JSWrapperObject): + * runtime/MathObject.cpp: + (JSC): + * runtime/NameInstance.h: + (NameInstance): + * runtime/RegExp.h: + * runtime/RegExpObject.cpp: + (JSC): + * runtime/SparseArrayValueMap.h: + * runtime/Structure.h: + (JSC::Structure): + (JSC::JSCell::classInfo): + (JSC): + * runtime/StructureChain.h: + * runtime/SymbolTable.h: + * testRegExp.cpp: + (GlobalObject::create): + +2012-09-17 Geoffrey Garen <ggaren@apple.com> + + Refactored the arguments object so it doesn't dictate closure layout + https://bugs.webkit.org/show_bug.cgi?id=96955 + + Reviewed by Oliver Hunt. + + * bytecode/CodeBlock.h: + (JSC::ExecState::argumentAfterCapture): Helper function for accessing an + argument that has been moved for capture. + + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::BytecodeGenerator): Generate metadata for arguments + that are captured. We don't move any arguments yet, but we do use this + metadata to tell the arguments object if an argument is stored in the + activation. + + * dfg/DFGOperations.cpp: + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compileGetByValOnArguments): + (JSC::DFG::SpeculativeJIT::compileGetArgumentsLength): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): Updated for the arguments object not + malloc'ing a separate backing store, and for a rename from deletedArguments + to slowArguments. + + * interpreter/CallFrame.h: + (ExecState): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::unwindCallFrame): + (JSC::Interpreter::privateExecute): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + * llint/LLIntSlowPaths.cpp: + (JSC::LLInt::LLINT_SLOW_PATH_DECL): Updated for small interface changes. + + * runtime/Arguments.cpp: + (JSC::Arguments::visitChildren): + (JSC::Arguments::copyToArguments): + (JSC::Arguments::fillArgList): + (JSC::Arguments::getOwnPropertySlotByIndex): + (JSC::Arguments::createStrictModeCallerIfNecessary): + (JSC::Arguments::createStrictModeCalleeIfNecessary): + (JSC::Arguments::getOwnPropertySlot): + (JSC::Arguments::getOwnPropertyDescriptor): + (JSC::Arguments::getOwnPropertyNames): + (JSC::Arguments::putByIndex): + (JSC::Arguments::put): + (JSC::Arguments::deletePropertyByIndex): + (JSC::Arguments::deleteProperty): + (JSC::Arguments::defineOwnProperty): + (JSC::Arguments::tearOff): Moved all data inline into the object, for speed, + and refactored all internal argument accesses to use helper functions, so + we can change the implementation without changing lots of code. + + (JSC::Arguments::didTearOffActivation): This function needs to account + for arguments that were moved by the activation object. We do this accounting + through a side vector that tells us where our arguments will be in the + activation. + + (JSC::Arguments::tearOffForInlineCallFrame): + * runtime/Arguments.h: + (Arguments): + (JSC::Arguments::length): + (JSC::Arguments::isTornOff): + (JSC::Arguments::Arguments): + (JSC::Arguments::allocateSlowArguments): + (JSC::Arguments::tryDeleteArgument): + (JSC::Arguments::trySetArgument): + (JSC::Arguments::tryGetArgument): + (JSC::Arguments::isDeletedArgument): + (JSC::Arguments::isArgument): + (JSC::Arguments::argument): + (JSC::Arguments::finishCreation): + + * runtime/JSActivation.h: + (JSC::JSActivation::create): + (JSActivation): + (JSC::JSActivation::captureStart): + (JSC::JSActivation::storageSize): + (JSC::JSActivation::registerOffset): + (JSC::JSActivation::isValid): The activation object is no longer responsible + for copying extra arguments provided by the caller. The argumnents object + does this instead. This means we can allocate and initialize an activation + without worrying about the call frame's argument count. + + * runtime/SymbolTable.h: + (JSC::SlowArgument::SlowArgument): + (SlowArgument): + (JSC): + (JSC::SharedSymbolTable::parameterCount): + (SharedSymbolTable): + (JSC::SharedSymbolTable::slowArguments): + (JSC::SharedSymbolTable::setSlowArguments): Added data structures to back + the algorithms above. + +2012-09-17 Filip Pizlo <fpizlo@apple.com> + + 32-bit LLInt get_by_val does vector length checks incorrectly + https://bugs.webkit.org/show_bug.cgi?id=96893 + <rdar://problem/12311678> + + Reviewed by Mark Hahnenberg. + + * llint/LowLevelInterpreter32_64.asm: + +2012-09-17 Filip Pizlo <fpizlo@apple.com> + + We don't have a bad enough time if an object's prototype chain crosses global objects + https://bugs.webkit.org/show_bug.cgi?id=96962 + + Reviewed by Geoffrey Garen. + + * runtime/JSGlobalObject.cpp: + (JSC): + +2012-09-17 Filip Pizlo <fpizlo@apple.com> + + Unreviewed, fix a broken assertion in offlineasm. + + * offlineasm/armv7.rb: + * offlineasm/backends.rb: + +2012-09-16 Mark Hahnenberg <mhahnenberg@apple.com> + + Delayed structure sweep can leak structures without bound + https://bugs.webkit.org/show_bug.cgi?id=96546 + + Reviewed by Gavin Barraclough. + + This patch gets rid of the separate Structure allocator in the MarkedSpace and adds two new destructor-only + allocators. We now have separate allocators for our three types of objects: those objects with no destructors, + those objects with destructors and with immortal structures, and those objects with destructors that don't have + immortal structures. All of the objects of the third type (destructors without immortal structures) now + inherit from a new class named JSDestructibleObject (which in turn is a subclass of JSNonFinalObject), which stores + the ClassInfo for these classes at a fixed offset for safe retrieval during sweeping/destruction. + + * API/JSCallbackConstructor.cpp: Use JSDestructibleObject for JSCallbackConstructor. + (JSC): + (JSC::JSCallbackConstructor::JSCallbackConstructor): + * API/JSCallbackConstructor.h: + (JSCallbackConstructor): + * API/JSCallbackObject.cpp: Inherit from JSDestructibleObject for normal JSCallbackObjects and use a finalizer for + JSCallbackObject<JSGlobalObject>, since JSGlobalObject also uses a finalizer. + (JSC): + (JSC::::create): We need to move the create function for JSCallbackObject<JSGlobalObject> out of line so we can add + the finalizer for it. We don't want to add the finalizer is something like finishCreation in case somebody decides + to subclass this. We use this same technique for many other subclasses of JSGlobalObject. + (JSC::::createStructure): + * API/JSCallbackObject.h: + (JSCallbackObject): + (JSC): + * API/JSClassRef.cpp: Change all the JSCallbackObject<JSNonFinalObject> to use JSDestructibleObject instead. + (OpaqueJSClass::prototype): + * API/JSObjectRef.cpp: Ditto. + (JSObjectMake): + (JSObjectGetPrivate): + (JSObjectSetPrivate): + (JSObjectGetPrivateProperty): + (JSObjectSetPrivateProperty): + (JSObjectDeletePrivateProperty): + * API/JSValueRef.cpp: Ditto. + (JSValueIsObjectOfClass): + * API/JSWeakObjectMapRefPrivate.cpp: Ditto. + * JSCTypedArrayStubs.h: + (JSC): + * JavaScriptCore.xcodeproj/project.pbxproj: + * dfg/DFGSpeculativeJIT.h: Use the proper allocator type when doing inline allocation in the DFG. + (JSC::DFG::SpeculativeJIT::emitAllocateBasicJSObject): + (JSC::DFG::SpeculativeJIT::emitAllocateJSFinalObject): + * heap/Heap.cpp: + (JSC): + * heap/Heap.h: Add accessors for the various types of allocators now. Also remove the isSafeToSweepStructures function + since it's always safe to sweep Structures now. + (JSC::Heap::allocatorForObjectWithNormalDestructor): + (JSC::Heap::allocatorForObjectWithImmortalStructureDestructor): + (Heap): + (JSC::Heap::allocateWithNormalDestructor): + (JSC): + (JSC::Heap::allocateWithImmortalStructureDestructor): + * heap/IncrementalSweeper.cpp: Remove all the logic to detect when it's safe to sweep Structures from the + IncrementalSweeper since it's always safe to sweep Structures now. + (JSC::IncrementalSweeper::IncrementalSweeper): + (JSC::IncrementalSweeper::sweepNextBlock): + (JSC::IncrementalSweeper::startSweeping): + (JSC::IncrementalSweeper::willFinishSweeping): + (JSC): + * heap/IncrementalSweeper.h: + (IncrementalSweeper): + * heap/MarkedAllocator.cpp: Remove the logic that was preventing us from sweeping Structures if it wasn't safe. Add + tracking of the specific destructor type of allocator. + (JSC::MarkedAllocator::tryAllocateHelper): + (JSC::MarkedAllocator::allocateBlock): + * heap/MarkedAllocator.h: + (JSC::MarkedAllocator::destructorType): + (MarkedAllocator): + (JSC::MarkedAllocator::MarkedAllocator): + (JSC::MarkedAllocator::init): + * heap/MarkedBlock.cpp: Add all the destructor type stuff to MarkedBlocks so that we do the right thing when sweeping. + We also use the stored destructor type to determine the right thing to do in all JSCell::classInfo() calls. + (JSC::MarkedBlock::create): + (JSC::MarkedBlock::MarkedBlock): + (JSC): + (JSC::MarkedBlock::specializedSweep): + (JSC::MarkedBlock::sweep): + (JSC::MarkedBlock::sweepHelper): + * heap/MarkedBlock.h: + (JSC): + (JSC::MarkedBlock::allocator): + (JSC::MarkedBlock::destructorType): + * heap/MarkedSpace.cpp: Add the new destructor allocators to MarkedSpace. + (JSC::MarkedSpace::MarkedSpace): + (JSC::MarkedSpace::resetAllocators): + (JSC::MarkedSpace::canonicalizeCellLivenessData): + (JSC::MarkedSpace::isPagedOut): + (JSC::MarkedSpace::freeBlock): + * heap/MarkedSpace.h: + (MarkedSpace): + (JSC::MarkedSpace::immortalStructureDestructorAllocatorFor): + (JSC::MarkedSpace::normalDestructorAllocatorFor): + (JSC::MarkedSpace::allocateWithImmortalStructureDestructor): + (JSC::MarkedSpace::allocateWithNormalDestructor): + (JSC::MarkedSpace::forEachBlock): + * heap/SlotVisitor.cpp: Add include because the symbol was needed in an inlined function. + * jit/JIT.h: Make sure we use the correct allocator when doing inline allocations in the baseline JIT. + * jit/JITInlineMethods.h: + (JSC::JIT::emitAllocateBasicJSObject): + (JSC::JIT::emitAllocateJSFinalObject): + (JSC::JIT::emitAllocateJSArray): + * jsc.cpp: + (GlobalObject::create): Add finalizer here since JSGlobalObject needs to use a finalizer instead of inheriting from + JSDestructibleObject. + * runtime/Arguments.cpp: Inherit from JSDestructibleObject. + (JSC): + * runtime/Arguments.h: + (Arguments): + (JSC::Arguments::Arguments): + * runtime/ErrorPrototype.cpp: Added an assert to make sure we have a trivial destructor. + (JSC): + * runtime/Executable.h: Indicate that all of the Executable* classes have immortal Structures. + (JSC): + * runtime/InternalFunction.cpp: Inherit from JSDestructibleObject. + (JSC): + (JSC::InternalFunction::InternalFunction): + * runtime/InternalFunction.h: + (InternalFunction): + * runtime/JSCell.h: Added the NEEDS_DESTRUCTOR macro to make it easier for classes to indicate that instead of being + allocated in a destructor MarkedAllocator that they will handle their destruction themselves through the + use of a finalizer. + (JSC): + (HasImmortalStructure): New template to help us determine at compile-time if a particular class + should be allocated in the immortal structure MarkedAllocator. The default value is false. In order + to be allocated in the immortal structure allocator, classes must specialize this template. Also added + a macro to make it easier for classes to specialize the template. + (JSC::allocateCell): Use the appropriate allocator depending on the destructor type. + * runtime/JSDestructibleObject.h: Added. New class that stores the ClassInfo of any subclass so that it can be + accessed safely when the object is being destroyed. + (JSC): + (JSDestructibleObject): + (JSC::JSDestructibleObject::classInfo): + (JSC::JSDestructibleObject::JSDestructibleObject): + (JSC::JSCell::classInfo): Checks the current MarkedBlock to see where it should get the ClassInfo from so that it's always safe. + * runtime/JSGlobalObject.cpp: JSGlobalObject now uses a finalizer instead of a destructor so that it can avoid forcing all + of its relatives in the inheritance hierarchy (e.g. JSScope) to use destructors as well. + (JSC::JSGlobalObject::reset): + * runtime/JSGlobalObject.h: + (JSGlobalObject): + (JSC::JSGlobalObject::createRareDataIfNeeded): Since we always create a finalizer now, we don't have to worry about adding one + for the m_rareData field when it's created. + (JSC::JSGlobalObject::create): + (JSC): + * runtime/JSGlobalThis.h: Inherit from JSDestructibleObject. + (JSGlobalThis): + (JSC::JSGlobalThis::JSGlobalThis): + * runtime/JSPropertyNameIterator.h: Has an immortal Structure. + (JSC): + * runtime/JSScope.cpp: + (JSC): + * runtime/JSString.h: Has an immortal Structure. + (JSC): + * runtime/JSWrapperObject.h: Inherit from JSDestructibleObject. + (JSWrapperObject): + (JSC::JSWrapperObject::JSWrapperObject): + * runtime/MathObject.cpp: Cleaning up some of the inheritance stuff. + (JSC): + * runtime/NameInstance.h: Inherit from JSDestructibleObject. + (NameInstance): + * runtime/RegExp.h: Has immortal Structure. + (JSC): + * runtime/RegExpObject.cpp: Inheritance cleanup. + (JSC): + * runtime/SparseArrayValueMap.h: Has immortal Structure. + (JSC): + * runtime/Structure.h: Has immortal Structure. + (JSC): + * runtime/StructureChain.h: Ditto. + (JSC): + * runtime/SymbolTable.h: Ditto. + (SharedSymbolTable): + (JSC): + +2012-09-17 Filip Pizlo <fpizlo@apple.com> + + If a prototype has indexed setters and its instances have indexed storage, then all put_by_val's should have a bad time + https://bugs.webkit.org/show_bug.cgi?id=96596 + + Reviewed by Gavin Barraclough. + + Added comprehensive support for accessors and read-only indexed properties on the + prototype chain. This is done without any performance regression on benchmarks that + we're aware of, by having the entire VM's strategy with respect to arrays tilted + heavily in favor of: + + - The prototype chain of JSArrays never having any accessors or read-only indexed + properties. If that changes, you're going to have a bad time. + + - Prototypes of non-JSArray objects either having no indexed accessors or read-only + indexed properties, or, having those indexed accessor thingies inserted before + any instance object (i.e. object with that prototype as its prototype) is created. + If you add indexed accessors or read-only indexed properties to an object that is + already used as a prototype, you're going to have a bad time. + + See below for the exact definition of having a bad time. + + Put another way, "fair" uses of indexed accessors and read-only indexed properties + are: + + - Put indexed accessors and read-only indexed properties on an object that is never + used as a prototype. This will slow down accesses to that object, but will not + have any effect on any other object. + + - Put those indexed accessor thingies on an object before it is used as a prototype + and then start instantiating objects that claim that object as their prototype. + This will slightly slow down indexed stores to the instance objects, and greatly + slow down all indexed accesses to the prototype, but will have no other effect. + + In short, "fair" uses only affect the object itself and any instance objects. But + if you start using indexed accessors in more eclectic ways, you're going to have + a bad time. + + Specifically, if an object that may be used as a prototype has an indexed accessor + added, the VM performs a whole-heap scan to find all objects that belong to the + same global object as the prototype you modified. If any of those objects has + indexed storage, their indexed storage is put into slow-put mode, just as if their + prototype chain had indexed accessors. This will happen even for objects that do + not currently have indexed accessors in their prototype chain. As well, all JSArray + allocations are caused to create arrays with slow-put storage, and all future + allocations of indexed storage for non-JSArray objects are also flipped to slow-put + mode. Note there are two aspects to having a bad time: (i) the whole-heap scan and + (ii) the poisoning of all indexed storage in the entire global object. (i) is + necessary for correctness. If we detect that an object that may be used as a + prototype has had an indexed accessor or indexed read-only property inserted into + it, then we need to ensure that henceforth all instances of that object inspect + the prototype chain whenever an indexed hole is stored to. But by default, indexed + stores do no such checking because doing so would be unnecessarily slow. So, we must + find all instances of the affected object and flip them into a different array + storage mode that omits all hole optimizations. Since prototypes never keep a list + of instance objects, the only way to find those objects is a whole-heap scan. But + (i) alone would be a potential disaster, if a program frequently allocated an + object without indexed accessors, then allocated a bunch of objects that used that + one as their prototype, and then added indexed accessors to the prototype. So, to + prevent massive heap scan storms in such awkward programs, having a bad time also + implies (ii): henceforth *all* objects belonging to that global object will use + slow put indexed storage, so that we don't ever have to scan the heap again. Note + that here we are using the global object as just an approximation of a program + module; it may be worth investigating in the future if other approximations can be + used instead. + + * bytecode/ArrayProfile.h: + (JSC): + (JSC::arrayModeFromStructure): + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::execute): + * dfg/DFGArrayMode.cpp: + (JSC::DFG::fromObserved): + (JSC::DFG::modeAlreadyChecked): + (JSC::DFG::modeToString): + * dfg/DFGArrayMode.h: + (DFG): + (JSC::DFG::isSlowPutAccess): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::checkArray): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * jit/JIT.h: + * jit/JITInlineMethods.h: + (JSC::JIT::emitAllocateJSArray): + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_new_array): + * runtime/ArrayPrototype.cpp: + (JSC::ArrayPrototype::finishCreation): + (JSC::arrayProtoFuncSort): + * runtime/IndexingType.h: + (JSC): + (JSC::hasIndexedProperties): + (JSC::hasIndexingHeader): + (JSC::hasArrayStorage): + (JSC::shouldUseSlowPut): + * runtime/JSArray.cpp: + (JSC::JSArray::pop): + (JSC::JSArray::push): + (JSC::JSArray::fillArgList): + (JSC::JSArray::copyToArguments): + * runtime/JSArray.h: + (JSC::JSArray::createStructure): + * runtime/JSGlobalObject.cpp: + (JSC::JSGlobalObject::JSGlobalObject): + (JSC::JSGlobalObject::reset): + (JSC): + (JSC::JSGlobalObject::haveABadTime): + * runtime/JSGlobalObject.h: + (JSGlobalObject): + (JSC::JSGlobalObject::addressOfArrayStructure): + (JSC::JSGlobalObject::havingABadTimeWatchpoint): + (JSC::JSGlobalObject::isHavingABadTime): + * runtime/JSObject.cpp: + (JSC::JSObject::visitButterfly): + (JSC::JSObject::getOwnPropertySlotByIndex): + (JSC::JSObject::put): + (JSC::JSObject::putByIndex): + (JSC::JSObject::enterDictionaryIndexingMode): + (JSC::JSObject::notifyPresenceOfIndexedAccessors): + (JSC): + (JSC::JSObject::createArrayStorage): + (JSC::JSObject::ensureArrayStorageExistsAndEnterDictionaryIndexingMode): + (JSC::JSObject::switchToSlowPutArrayStorage): + (JSC::JSObject::setPrototype): + (JSC::JSObject::resetInheritorID): + (JSC::JSObject::inheritorID): + (JSC::JSObject::allowsAccessFrom): + (JSC::JSObject::deletePropertyByIndex): + (JSC::JSObject::getOwnPropertyNames): + (JSC::JSObject::unwrappedGlobalObject): + (JSC::JSObject::notifyUsedAsPrototype): + (JSC::JSObject::createInheritorID): + (JSC::JSObject::defineOwnIndexedProperty): + (JSC::JSObject::attemptToInterceptPutByIndexOnHoleForPrototype): + (JSC::JSObject::attemptToInterceptPutByIndexOnHole): + (JSC::JSObject::putByIndexBeyondVectorLength): + (JSC::JSObject::putDirectIndexBeyondVectorLength): + (JSC::JSObject::getNewVectorLength): + (JSC::JSObject::getOwnPropertyDescriptor): + * runtime/JSObject.h: + (JSC::JSObject::mayBeUsedAsPrototype): + (JSObject): + (JSC::JSObject::mayInterceptIndexedAccesses): + (JSC::JSObject::getArrayLength): + (JSC::JSObject::getVectorLength): + (JSC::JSObject::canGetIndexQuickly): + (JSC::JSObject::getIndexQuickly): + (JSC::JSObject::canSetIndexQuickly): + (JSC::JSObject::setIndexQuickly): + (JSC::JSObject::initializeIndex): + (JSC::JSObject::completeInitialization): + (JSC::JSObject::inSparseIndexingMode): + (JSC::JSObject::arrayStorage): + (JSC::JSObject::arrayStorageOrNull): + (JSC::JSObject::ensureArrayStorage): + (JSC): + (JSC::JSValue::putByIndex): + * runtime/JSValue.cpp: + (JSC::JSValue::putToPrimitive): + (JSC::JSValue::putToPrimitiveByIndex): + (JSC): + * runtime/JSValue.h: + (JSValue): + * runtime/ObjectPrototype.cpp: + (JSC::ObjectPrototype::finishCreation): + * runtime/SparseArrayValueMap.cpp: + (JSC::SparseArrayValueMap::putEntry): + (JSC::SparseArrayEntry::put): + (JSC): + * runtime/SparseArrayValueMap.h: + (JSC): + (SparseArrayEntry): + * runtime/Structure.cpp: + (JSC::Structure::anyObjectInChainMayInterceptIndexedAccesses): + (JSC): + (JSC::Structure::suggestedIndexingTransition): + * runtime/Structure.h: + (Structure): + (JSC::Structure::mayInterceptIndexedAccesses): + * runtime/StructureTransitionTable.h: + (JSC::newIndexingType): + +2012-09-17 Filip Pizlo <fpizlo@apple.com> + + Array profiling has convergence issues + https://bugs.webkit.org/show_bug.cgi?id=96891 + + Reviewed by Gavin Barraclough. + + Now each array profiling site merges in the indexing type it observed into + the m_observedArrayModes bitset. The ArrayProfile also uses this to detect + cases where the structure must have gone polymorphic (if the bitset is + polymorphic then the structure must be). This achieves something like the + best of both worlds: on the one hand, we get a probabilistic structure that + we can use to optimize the monomorphic structure case, but on the other hand, + we get an accurate view of the set of types that were encountered. + + * assembler/MacroAssemblerARMv7.h: + (JSC::MacroAssemblerARMv7::or32): + (MacroAssemblerARMv7): + * assembler/MacroAssemblerX86.h: + (JSC::MacroAssemblerX86::or32): + (MacroAssemblerX86): + * assembler/MacroAssemblerX86_64.h: + (JSC::MacroAssemblerX86_64::or32): + (MacroAssemblerX86_64): + * assembler/X86Assembler.h: + (X86Assembler): + (JSC::X86Assembler::orl_rm): + * bytecode/ArrayProfile.cpp: + (JSC::ArrayProfile::computeUpdatedPrediction): + * bytecode/ArrayProfile.h: + (JSC::ArrayProfile::addressOfArrayModes): + (JSC::ArrayProfile::structureIsPolymorphic): + * jit/JIT.h: + (JIT): + * jit/JITInlineMethods.h: + (JSC): + (JSC::JIT::emitArrayProfilingSite): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::emit_op_get_by_val): + (JSC::JIT::emit_op_put_by_val): + (JSC::JIT::privateCompilePatchGetArrayLength): + * jit/JITPropertyAccess32_64.cpp: + (JSC::JIT::emit_op_get_by_val): + (JSC::JIT::emit_op_put_by_val): + (JSC::JIT::privateCompilePatchGetArrayLength): + * llint/LowLevelInterpreter.asm: + * llint/LowLevelInterpreter32_64.asm: + * llint/LowLevelInterpreter64.asm: + +2012-09-17 Mark Lam <mark.lam@apple.com> + + Not reviewed. Added svn:eol-style native to unbreak some build bots. + https://bugs.webkit.org/show_bug.cgi?id=96175. + + * JavaScriptCore.vcproj/LLIntAssembly/LLIntAssembly.vcproj: Added property svn:eol-style. + * JavaScriptCore.vcproj/LLIntDesiredOffsets/LLIntDesiredOffsets.vcproj: Added property svn:eol-style. + * JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractor.vcproj: Added property svn:eol-style. + +2012-09-16 Mark Lam <mark.lam@apple.com> + + Added MSVC project changes to enable building the llint. + https://bugs.webkit.org/show_bug.cgi?id=96175. + + Reviewed by Geoff Garen. + + This only adds the ability to build the llint, but currently, only the + C++ backend is supported. By default, the Windows port will remain + running with the baseline JIT. The llint will not be enabled. + + * JavaScriptCore.vcproj/JavaScriptCore.sln: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.vcproj/LLIntAssembly: Added. + * JavaScriptCore.vcproj/LLIntAssembly/LLIntAssembly.make: Added. + * JavaScriptCore.vcproj/LLIntAssembly/LLIntAssembly.vcproj: Added. + * JavaScriptCore.vcproj/LLIntAssembly/build-LLIntAssembly.sh: Added. + * JavaScriptCore.vcproj/LLIntDesiredOffsets: Added. + * JavaScriptCore.vcproj/LLIntDesiredOffsets/LLIntDesiredOffsets.make: Added. + * JavaScriptCore.vcproj/LLIntDesiredOffsets/LLIntDesiredOffsets.vcproj: Added. + * JavaScriptCore.vcproj/LLIntDesiredOffsets/build-LLIntDesiredOffsets.sh: Added. + * JavaScriptCore.vcproj/LLIntOffsetsExtractor: Added. + * JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractor.vcproj: Added. + * JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorCommon.vsprops: Added. + * JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorDebug.vsprops: Added. + * JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorRelease.vsprops: Added. + +2012-09-16 Filip Pizlo <fpizlo@apple.com> + + JSObject.cpp and JSArray.cpp have inconsistent tests for the invalid array index case + https://bugs.webkit.org/show_bug.cgi?id=96878 + + Reviewed by Sam Weinig. + + Removed the uses of UNLIKELY() because I don't believe they are buying us anything, + since we're already on the slow path. Also found other places where we're testing for + the invalid array index case using unusual predicates rather than just using + MAX_ARRAY_INDEX. With this change, I believe that all of our tests for invalid + array indices (i.e. indices that should be treated as non-indexed properties) + uniformly use MAX_ARRAY_INDEX and PropertyName::NotAnIndex. + + * runtime/JSArray.cpp: + (JSC::JSArray::push): + * runtime/JSObject.cpp: + (JSC::JSObject::putByIndex): + (JSC::JSObject::defineOwnIndexedProperty): + +2012-09-15 Filip Pizlo <fpizlo@apple.com> + + Following the Butterfly refactoring, the comment for lastArraySize was not updated + https://bugs.webkit.org/show_bug.cgi?id=96877 + + Reviewed by Sam Weinig. + + * runtime/JSObject.cpp: + (JSC): + +2012-09-15 Mark Lam <mark.lam@apple.com> + + Fixed JSLock to use the platform abstraction for Mutex instead of + depending on pthreads. + https://bugs.webkit.org/show_bug.cgi?id=96858. + + Reviewed by Filip Pizlo. + + This fixes a synchronization problem on the Windows port and makes + it more reliable when running the layout tests. + + * runtime/InitializeThreading.cpp: + (JSC::initializeThreadingOnce): + * runtime/JSLock.cpp: + (JSC): + (JSC::GlobalJSLock::GlobalJSLock): + (JSC::GlobalJSLock::~GlobalJSLock): + (JSC::GlobalJSLock::initialize): + * runtime/JSLock.h: + (GlobalJSLock): + (JSLock): + +2012-09-15 Filip Pizlo <fpizlo@apple.com> + + Structure check hoisting fails to consider the possibility of conflicting checks on the source of the first assignment to the hoisted variable + https://bugs.webkit.org/show_bug.cgi?id=96872 + + Reviewed by Oliver Hunt. + + This does a few related things: + + - It turns off the use of ForceOSRExit for sure-to-fail CheckStructures, because + I noticed that this would sometimes happen for a ForwardCheckStructure. The + problem is that ForceOSRExit exits backwards, not forwards. Since the code that + led to those ForceOSRExit's being inserted was written out of paranoia rather + than need, I removed it. Specifically, I removed the m_isValid = false code + for CheckStructure/StructureTransitionWatchpoint in AbstractState. + + - If a structure check causes a structure set to go empty, we don't want a + PutStructure to revive the set. It should instead be smart enough to realize + that an empty set implies that the code can't execute. This was the only "bug" + that the use of m_isValid = false was preventing. + + - Finally, the main change: structure check hoisting looks at the source of the + SetLocals on structure-check-hoistable variables and ensures that the source + is not checked with a conflicting structure. This is O(n^2) but it does not + show up at all in performance tests. + + The first two parts of this change were auxiliary bugs that were revealed by + the structure check hoister doing bad things. + + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::initialize): + (JSC::DFG::AbstractState::execute): + * dfg/DFGStructureCheckHoistingPhase.cpp: + (JSC::DFG::StructureCheckHoistingPhase::run): + +2012-09-14 Filip Pizlo <fpizlo@apple.com> + + All of the things in SparseArrayValueMap should be out-of-line + https://bugs.webkit.org/show_bug.cgi?id=96854 + + Reviewed by Andy Estes. + + Those inline methods were buying us nothing. + + * GNUmakefile.list.am: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * runtime/JSArray.cpp: + * runtime/JSGlobalData.cpp: + * runtime/JSObject.cpp: + * runtime/RegExpMatchesArray.cpp: + * runtime/SparseArrayValueMap.cpp: + (JSC::SparseArrayValueMap::SparseArrayValueMap): + (JSC): + (JSC::SparseArrayValueMap::~SparseArrayValueMap): + (JSC::SparseArrayValueMap::finishCreation): + (JSC::SparseArrayValueMap::create): + (JSC::SparseArrayValueMap::destroy): + (JSC::SparseArrayValueMap::createStructure): + (JSC::SparseArrayValueMap::add): + (JSC::SparseArrayValueMap::putEntry): + (JSC::SparseArrayValueMap::putDirect): + (JSC::SparseArrayEntry::get): + (JSC::SparseArrayEntry::getNonSparseMode): + (JSC::SparseArrayValueMap::visitChildren): + * runtime/SparseArrayValueMapInlineMethods.h: Removed. + +2012-09-14 Mike West <mkwst@chromium.org> + + JSC should throw a more descriptive exception when blocking 'eval' via CSP. + https://bugs.webkit.org/show_bug.cgi?id=94331 + + Reviewed by Geoffrey Garen. + + Unless explicitly whitelisted, the 'script-src' Content Security Policy + directive blocks 'eval' and 'eval'-like constructs such as + 'new Function()'. When 'eval' is encountered in code, an 'EvalError' is + thrown, but the associated message is poor: "Eval is disabled" doesn't + give developers enough information about why their code isn't behaving + as expected. + + This patch adds an 'errorMessage' parameter to the JavaScriptCore method + used to disable 'eval'; ContentSecurityPolicy has the opportunity to + pass in a more detailed and descriptive error that contains more context + for the developer. + + * runtime/Executable.cpp: + (JSC::EvalExecutable::compileInternal): + Drop the hard-coded "Eval is disabled" error message in favor of + reading the error message off the global object. + * runtime/FunctionConstructor.cpp: + (JSC::FunctionConstructor::getCallData): + Drop the hard-coded "Function constructor is disabled" error message + in favor of reading the error message off the global object. + * runtime/JSGlobalObject.h: + (JSGlobalObject): + (JSC::JSGlobalObject::evalEnabled): + Making this accessor method const. + (JSC::JSGlobalObject::evalDisabledErrorMessage): + Accessor for the error message set via 'setEvalDisabled'. + (JSC::JSGlobalObject::setEvalEnabled): + Adding an 'errorMessage' parameter which is stored on the global + object, and used when exceptions are thrown. + +2012-09-14 Filip Pizlo <fpizlo@apple.com> + + bbc homepage crashes immediately + https://bugs.webkit.org/show_bug.cgi?id=96812 + <rdar://problem/12081386> + + Reviewed by Oliver Hunt. + + If you use the old storage pointer to write to space you thought was newly allocated, + you're going to have a bad time. + + * runtime/JSArray.cpp: + (JSC::JSArray::unshiftCount): + +2012-09-14 Adam Barth <abarth@webkit.org> + + Remove webkitPostMessage + https://bugs.webkit.org/show_bug.cgi?id=96577 + + Reviewed by Ojan Vafai. + + Add ENABLE_LEGACY_VENDOR_PREFIXES flag. + + * Configurations/FeatureDefines.xcconfig: + +2012-09-14 Tor Arne Vestbø <tor.arne.vestbo@nokia.com> + + [Qt] Make force_static_libs_as_shared work on Mac OS + + We had to move a few LIBS += around that were in the wrong place, + and not caught when everything was just linked into the final + QtWebKit library. + + Reviewed by Simon Hausmann. + + * jsc.pro: No need for AppKit, we get it from WTF.pri + +2012-09-14 Kevin Funk <kevin.funk@kdab.com> + + Fix interpreter build + https://bugs.webkit.org/show_bug.cgi?id=96617 + + Reviewed by Simon Hausmann. + + Make compile. + + * interpreter/Interpreter.cpp: + 2012-09-14 Parth Patel <parpatel@rim.com> [BlackBerry] Switching from Slogger to Slogger2 requires changes in CMakeList of diff --git a/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig b/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig index f9a0eb29c..ec35cf673 100644 --- a/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig +++ b/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig @@ -95,6 +95,7 @@ ENABLE_LEGACY_NOTIFICATIONS_macosx = $(ENABLE_LEGACY_NOTIFICATIONS_macosx_$(TARG ENABLE_LEGACY_NOTIFICATIONS_macosx_1070 = ; ENABLE_LEGACY_NOTIFICATIONS_macosx_1080 = ENABLE_LEGACY_NOTIFICATIONS; ENABLE_LEGACY_NOTIFICATIONS_macosx_1090 = ENABLE_LEGACY_NOTIFICATIONS; +ENABLE_LEGACY_VENDOR_PREFIXES = ENABLE_LEGACY_VENDOR_PREFIXES; ENABLE_LINK_PREFETCH = ; ENABLE_LINK_PRERENDER = ; ENABLE_MATHML = ENABLE_MATHML; @@ -139,4 +140,4 @@ ENABLE_WIDGET_REGION_macosx = ENABLE_WIDGET_REGION; 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_CSS_BOX_DECORATION_BREAK) $(ENABLE_CSS_EXCLUSIONS) $(ENABLE_CSS_FILTERS) $(ENABLE_CSS_HIERARCHIES) $(ENABLE_CSS_IMAGE_ORIENTATION) $(ENABLE_CSS_IMAGE_RESOLUTION) $(ENABLE_CSS_REGIONS) $(ENABLE_CSS_SHADERS) $(ENABLE_CSS_COMPOSITING) $(ENABLE_CSS_STICKY_POSITION) $(ENABLE_CSS_VARIABLES) $(ENABLE_CSS3_TEXT_DECORATION) $(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_NAVIGATOR_CONTENT_UTILS) $(ENABLE_NOTIFICATIONS) $(ENABLE_PAGE_VISIBILITY_API) $(ENABLE_PROGRESS_ELEMENT) $(ENABLE_QUOTA) $(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_WIDGET_REGION) $(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_HIERARCHIES) $(ENABLE_CSS_IMAGE_ORIENTATION) $(ENABLE_CSS_IMAGE_RESOLUTION) $(ENABLE_CSS_REGIONS) $(ENABLE_CSS_SHADERS) $(ENABLE_CSS_COMPOSITING) $(ENABLE_CSS_STICKY_POSITION) $(ENABLE_CSS_VARIABLES) $(ENABLE_CSS3_TEXT_DECORATION) $(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_LEGACY_VENDOR_PREFIXES) $(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_NAVIGATOR_CONTENT_UTILS) $(ENABLE_NOTIFICATIONS) $(ENABLE_PAGE_VISIBILITY_API) $(ENABLE_PROGRESS_ELEMENT) $(ENABLE_QUOTA) $(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_WIDGET_REGION) $(ENABLE_WORKERS) $(ENABLE_XSLT); diff --git a/Source/JavaScriptCore/Configurations/Version.xcconfig b/Source/JavaScriptCore/Configurations/Version.xcconfig index 5cb8681fa..83578f9e9 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 = 10; +MINOR_VERSION = 11; TINY_VERSION = 0; FULL_VERSION = $(MAJOR_VERSION).$(MINOR_VERSION); diff --git a/Source/JavaScriptCore/GNUmakefile.list.am b/Source/JavaScriptCore/GNUmakefile.list.am index b1715248c..e79542f9e 100644 --- a/Source/JavaScriptCore/GNUmakefile.list.am +++ b/Source/JavaScriptCore/GNUmakefile.list.am @@ -647,7 +647,6 @@ javascriptcore_sources += \ Source/JavaScriptCore/runtime/SamplingCounter.h \ Source/JavaScriptCore/runtime/SmallStrings.cpp \ Source/JavaScriptCore/runtime/SmallStrings.h \ - Source/JavaScriptCore/runtime/SparseArrayValueMapInlineMethods.h \ Source/JavaScriptCore/runtime/SparseArrayValueMap.cpp \ Source/JavaScriptCore/runtime/SparseArrayValueMap.h \ Source/JavaScriptCore/runtime/StrictEvalActivation.cpp \ diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.sln b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.sln index 787abc182..6f4236e03 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.sln +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.sln @@ -4,6 +4,9 @@ Microsoft Visual Studio Solution File, Format Version 9.00 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JavaScriptCore", "JavaScriptCore\JavaScriptCore.vcproj", "{011D10F1-B656-4A1B-A0C3-3842F02122C5}"
ProjectSection(ProjectDependencies) = postProject
{4FF5BA11-59EC-4C24-8F52-F235C2E7D43A} = {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}
+ {9221744B-5715-4F56-9590-42F7AB23DD8B} = {9221744B-5715-4F56-9590-42F7AB23DD8B}
+ {D595E3F6-24F2-4C60-935C-95D50C6B3E96} = {D595E3F6-24F2-4C60-935C-95D50C6B3E96}
+ {877150A0-41B3-4730-9D98-1B8298098B14} = {877150A0-41B3-4730-9D98-1B8298098B14}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jsc", "jsc\jsc.vcproj", "{C59E5129-B453-49B7-A52B-1E104715F76E}"
@@ -28,6 +31,30 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testRegExp", "testRegExp\te EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WTFGenerated", "..\..\WTF\WTF.vcproj\WTFGenerated.vcproj", "{5AE5F5E4-782D-4F63-B4D7-3977B52B9950}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LLIntDesiredOffsets", "LLIntDesiredOffsets\LLIntDesiredOffsets.vcproj", "{877150A0-41B3-4730-9D98-1B8298098B14}"
+ ProjectSection(ProjectDependencies) = postProject
+ {5AE5F5E4-782D-4F63-B4D7-3977B52B9950} = {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}
+ {AA8A5A85-592B-4357-BC60-E0E91E026AF6} = {AA8A5A85-592B-4357-BC60-E0E91E026AF6}
+ {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A} = {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LLIntOffsetsExtractor", "LLIntOffsetsExtractor\LLIntOffsetsExtractor.vcproj", "{D595E3F6-24F2-4C60-935C-95D50C6B3E96}"
+ ProjectSection(ProjectDependencies) = postProject
+ {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A} = {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}
+ {AA8A5A85-592B-4357-BC60-E0E91E026AF6} = {AA8A5A85-592B-4357-BC60-E0E91E026AF6}
+ {877150A0-41B3-4730-9D98-1B8298098B14} = {877150A0-41B3-4730-9D98-1B8298098B14}
+ {5AE5F5E4-782D-4F63-B4D7-3977B52B9950} = {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LLIntAssembly", "LLIntAssembly\LLIntAssembly.vcproj", "{9221744B-5715-4F56-9590-42F7AB23DD8B}"
+ ProjectSection(ProjectDependencies) = postProject
+ {D595E3F6-24F2-4C60-935C-95D50C6B3E96} = {D595E3F6-24F2-4C60-935C-95D50C6B3E96}
+ {5AE5F5E4-782D-4F63-B4D7-3977B52B9950} = {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}
+ {877150A0-41B3-4730-9D98-1B8298098B14} = {877150A0-41B3-4730-9D98-1B8298098B14}
+ {AA8A5A85-592B-4357-BC60-E0E91E026AF6} = {AA8A5A85-592B-4357-BC60-E0E91E026AF6}
+ {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A} = {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}
+ EndProjectSection
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug_All|Win32 = Debug_All|Win32
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj index d75be0b67..f5cbbb150 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj @@ -518,10 +518,6 @@ >
</File>
<File
- RelativePath="..\..\runtime\SparseArrayValueMapInlineMethods.h"
- >
- </File>
- <File
RelativePath="..\..\runtime\ArrayStorage.h"
>
</File>
@@ -965,14 +961,14 @@ RelativePath="..\..\runtime\JSString.h"
>
</File>
- <File
- RelativePath="..\..\runtime\JSStringJoiner.cpp"
- >
- </File>
- <File
- RelativePath="..\..\runtime\JSStringJoiner.h"
- >
- </File>
+ <File
+ RelativePath="..\..\runtime\JSStringJoiner.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\runtime\JSStringJoiner.h"
+ >
+ </File>
<File
RelativePath="..\..\runtime\JSSymbolTableObject.cpp"
>
@@ -2022,9 +2018,73 @@ Name="llint"
>
<File
+ RelativePath="..\..\llint\LLIntCLoop.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\llint\LLIntCLoop.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\llint\LLIntCommon.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\llint\LLIntData.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\llint\LLIntData.h"
>
</File>
+ <File
+ RelativePath="..\..\llint\LLIntEntrypoints.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\llint\LLIntEntrypoints.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\llint\LLIntExceptions.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\llint\LLIntExceptions.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\llint\LLIntOfflineAsmConfig.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\llint\LLIntOpcode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\llint\LLIntSlowPaths.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\llint\LLIntSlowPaths.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\llint\LLIntThunks.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\llint\LLIntThunks.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\llint\LowLevelInterpreter.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\llint\LowLevelInterpreter.h"
+ >
+ </File>
</Filter>
<Filter
Name="disassembler"
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntAssembly/LLIntAssembly.make b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntAssembly/LLIntAssembly.make new file mode 100644 index 000000000..ea4a72902 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntAssembly/LLIntAssembly.make @@ -0,0 +1,9 @@ +all: + touch "%ConfigurationBuildDir%\buildfailed" + bash build-LLIntAssembly.sh "%ConfigurationBuildDir%" "$(WEBKITLIBRARIESDIR)" + -del "%ConfigurationBuildDir%\buildfailed" + +clean: + -del "%ConfigurationBuildDir%\buildfailed" + -del /s /q "%ConfigurationBuildDir%\obj\LLIntOffsetsExtractor\LLIntOffsetsExtractor.exe" + -del /s /q "%ConfigurationBuildDir%\obj\JavaScriptCore\DerivedSources\LLIntAssembly.h" diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntAssembly/LLIntAssembly.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntAssembly/LLIntAssembly.vcproj new file mode 100644 index 000000000..ed6aae895 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntAssembly/LLIntAssembly.vcproj @@ -0,0 +1,173 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="LLIntAssembly"
+ ProjectGUID="{9221744B-5715-4F56-9590-42F7AB23DD8B}"
+ RootNamespace="LLIntAssembly"
+ Keyword="MakeFileProj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ ConfigurationType="0"
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntAssembly.make"
+ ReBuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntAssembly.make clean
nmake -f LLIntAssembly.make"
+ CleanCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntAssembly.make clean"
+ Output="LLIntAssembly.h"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ ConfigurationType="0"
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntAssembly.make"
+ ReBuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntAssembly.make clean
nmake -f LLIntAssembly.make"
+ CleanCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntAssembly.make clean"
+ Output="LLIntAssembly.h"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug_Cairo_CFLite|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ ConfigurationType="0"
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntAssembly.make"
+ ReBuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntAssembly.make clean
nmake -f LLIntAssembly.make"
+ CleanCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntAssembly.make clean"
+ Output="LLIntAssembly.h"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug_All|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ ConfigurationType="0"
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntAssembly.make"
+ ReBuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntAssembly.make clean
nmake -f LLIntAssembly.make"
+ CleanCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntAssembly.make clean"
+ Output="LLIntAssembly.h"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Production|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ ConfigurationType="0"
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntAssembly.make"
+ ReBuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntAssembly.make clean
nmake -f LLIntAssembly.make"
+ CleanCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntAssembly.make clean"
+ Output="LLIntAssembly.h"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Release_Cairo_CFLite|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ ConfigurationType="0"
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntAssembly.make"
+ ReBuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntAssembly.make clean
nmake -f LLIntAssembly.make"
+ CleanCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntAssembly.make clean"
+ Output="LLIntAssembly.h"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Release_PGO|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ ConfigurationType="0"
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntAssembly.make"
+ ReBuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntAssembly.make clean
nmake -f LLIntAssembly.make"
+ CleanCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntAssembly.make clean"
+ Output="LLIntAssembly.h"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath=".\build-LLIntAssembly.sh"
+ >
+ </File>
+ <File
+ RelativePath=".\LLIntAssembly.make"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntAssembly/build-LLIntAssembly.sh b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntAssembly/build-LLIntAssembly.sh new file mode 100755 index 000000000..a809be776 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntAssembly/build-LLIntAssembly.sh @@ -0,0 +1,26 @@ +#!/usr/bin/bash + +SRCROOT="`pwd`/../.." +SRCROOT=`realpath "$SRCROOT"` +# Do a little dance to get the path into 8.3 form to make it safe for gnu make +# http://bugzilla.opendarwin.org/show_bug.cgi?id=8173 +SRCROOT=`cygpath -m -s "$SRCROOT"` +SRCROOT=`cygpath -u "$SRCROOT"` +export SRCROOT + +XDSTROOT="$1" +export XDSTROOT +# Do a little dance to get the path into 8.3 form to make it safe for gnu make +# http://bugzilla.opendarwin.org/show_bug.cgi?id=8173 +XDSTROOT=`cygpath -m -s "$XDSTROOT"` +XDSTROOT=`cygpath -u "$XDSTROOT"` +export XDSTROOT + +export BUILT_PRODUCTS_DIR="$XDSTROOT/obj" + +cd "${BUILT_PRODUCTS_DIR}/JavaScriptCore/DerivedSources" + +############################################################################## +# Step 3: Build LLIntOffsetsExtractor + +/usr/bin/env ruby "${SRCROOT}/offlineasm/asm.rb" "${SRCROOT}/llint/LowLevelInterpreter.asm" "${BUILT_PRODUCTS_DIR}/LLIntOffsetsExtractor/LLIntOffsetsExtractor.exe" "LLIntAssembly.h" || exit 1 diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntDesiredOffsets/LLIntDesiredOffsets.make b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntDesiredOffsets/LLIntDesiredOffsets.make new file mode 100644 index 000000000..996c92377 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntDesiredOffsets/LLIntDesiredOffsets.make @@ -0,0 +1,9 @@ +all: + touch "%ConfigurationBuildDir%\buildfailed" + bash build-LLIntDesiredOffsets.sh "%ConfigurationBuildDir%" "$(WEBKITLIBRARIESDIR)" + + -del "%ConfigurationBuildDir%\buildfailed" + +clean: + -del "%ConfigurationBuildDir%\buildfailed" + -del /s /q "%ConfigurationBuildDir%\obj\JavaScriptCore\DerivedSources\LLIntDesiredOffsets.h" diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntDesiredOffsets/LLIntDesiredOffsets.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntDesiredOffsets/LLIntDesiredOffsets.vcproj new file mode 100644 index 000000000..0ece351b0 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntDesiredOffsets/LLIntDesiredOffsets.vcproj @@ -0,0 +1,173 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="LLIntDesiredOffsets"
+ ProjectGUID="{877150A0-41B3-4730-9D98-1B8298098B14}"
+ RootNamespace="LLIntDesiredOffsets"
+ Keyword="MakeFileProj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ IntermediateDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ ConfigurationType="0"
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntDesiredOffsets.make"
+ ReBuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntDesiredOffsets.make clean
nmake -f LLIntDesiredOffsets.make"
+ CleanCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntDesiredOffsets.make clean"
+ Output="LLIntDesiredOffsets.h"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ IntermediateDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ ConfigurationType="0"
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntDesiredOffsets.make"
+ ReBuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntDesiredOffsets.make clean
nmake -f LLIntDesiredOffsets.make"
+ CleanCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntDesiredOffsets.make clean"
+ Output="LLIntDesiredOffsets.h"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug_Cairo_CFLite|Win32"
+ OutputDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ IntermediateDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ ConfigurationType="0"
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntDesiredOffsets.make"
+ ReBuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntDesiredOffsets.make clean
nmake -f LLIntDesiredOffsets.make"
+ CleanCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntDesiredOffsets.make clean"
+ Output="LLIntDesiredOffsets.h"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug_All|Win32"
+ OutputDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ IntermediateDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ ConfigurationType="0"
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntDesiredOffsets.make"
+ ReBuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntDesiredOffsets.make clean
nmake -f LLIntDesiredOffsets.make"
+ CleanCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntDesiredOffsets.make clean"
+ Output="LLIntDesiredOffsets.h"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Production|Win32"
+ OutputDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ IntermediateDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ ConfigurationType="0"
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntDesiredOffsets.make"
+ ReBuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntDesiredOffsets.make clean
nmake -f LLIntDesiredOffsets.make"
+ CleanCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntDesiredOffsets.make clean"
+ Output="LLIntDesiredOffsets.h"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Release_Cairo_CFLite|Win32"
+ OutputDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ IntermediateDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ ConfigurationType="0"
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntDesiredOffsets.make"
+ ReBuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntDesiredOffsets.make clean
nmake -f LLIntDesiredOffsets.make"
+ CleanCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntDesiredOffsets.make clean"
+ Output="LLIntDesiredOffsets.h"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Release_PGO|Win32"
+ OutputDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ IntermediateDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ ConfigurationType="0"
+ >
+ <Tool
+ Name="VCNMakeTool"
+ BuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntDesiredOffsets.make"
+ ReBuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntDesiredOffsets.make clean
nmake -f LLIntDesiredOffsets.make"
+ CleanCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f LLIntDesiredOffsets.make clean"
+ Output="LLIntDesiredOffsets.h"
+ PreprocessorDefinitions=""
+ IncludeSearchPath=""
+ ForcedIncludes=""
+ AssemblySearchPath=""
+ ForcedUsingAssemblies=""
+ CompileAsManaged=""
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath=".\build-LLIntDesiredOffsets.sh"
+ >
+ </File>
+ <File
+ RelativePath=".\LLIntDesiredOffsets.make"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntDesiredOffsets/build-LLIntDesiredOffsets.sh b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntDesiredOffsets/build-LLIntDesiredOffsets.sh new file mode 100755 index 000000000..57d715ca1 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntDesiredOffsets/build-LLIntDesiredOffsets.sh @@ -0,0 +1,25 @@ +#!/usr/bin/bash + +SRCROOT="`pwd`/../.." +SRCROOT=`realpath "$SRCROOT"` +# Do a little dance to get the path into 8.3 form to make it safe for gnu make +# http://bugzilla.opendarwin.org/show_bug.cgi?id=8173 +SRCROOT=`cygpath -m -s "$SRCROOT"` +SRCROOT=`cygpath -u "$SRCROOT"` +export SRCROOT + +XDSTROOT="$1" +export XDSTROOT +# Do a little dance to get the path into 8.3 form to make it safe for gnu make +# http://bugzilla.opendarwin.org/show_bug.cgi?id=8173 +XDSTROOT=`cygpath -m -s "$XDSTROOT"` +XDSTROOT=`cygpath -u "$XDSTROOT"` +export XDSTROOT + +export BUILT_PRODUCTS_DIR="$XDSTROOT/obj/JavaScriptCore/DerivedSources" + +############################################################################## +# Step 1: Generate LLIntDesiredOffsets.h +mkdir -p "${BUILT_PRODUCTS_DIR}" + +/usr/bin/env ruby "${SRCROOT}/offlineasm/generate_offset_extractor.rb" "${SRCROOT}/llint/LowLevelInterpreter.asm" "${BUILT_PRODUCTS_DIR}/LLIntDesiredOffsets.h" diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractor.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractor.vcproj new file mode 100644 index 000000000..4862b658a --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractor.vcproj @@ -0,0 +1,476 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="LLIntOffsetsExtractor"
+ ProjectGUID="{D595E3F6-24F2-4C60-935C-95D50C6B3E96}"
+ RootNamespace="LLIntOffsetsExtractor"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(ConfigurationBuildDir)\obj\LLIntOffsetsExtractor"
+ IntermediateDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ ConfigurationType="1"
+ InheritedPropertySheets=".\LLIntOffsetsExtractorDebug.vsprops"
+ CharacterSet="1"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(ConfigurationBuildDir)\obj\LLIntOffsetsExtractor"
+ IntermediateDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ ConfigurationType="1"
+ InheritedPropertySheets=".\LLIntOffsetsExtractorRelease.vsprops"
+ CharacterSet="1"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug_Cairo_CFLite|Win32"
+ OutputDirectory="$(ConfigurationBuildDir)\obj\LLIntOffsetsExtractor"
+ IntermediateDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ ConfigurationType="1"
+ InheritedPropertySheets=".\LLIntOffsetsExtractorDebugCairoCFLite.vsprops"
+ CharacterSet="1"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug_All|Win32"
+ OutputDirectory="$(ConfigurationBuildDir)\obj\LLIntOffsetsExtractor"
+ IntermediateDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ ConfigurationType="1"
+ InheritedPropertySheets=".\LLIntOffsetsExtractorDebugAll.vsprops"
+ CharacterSet="1"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Production|Win32"
+ OutputDirectory="$(ConfigurationBuildDir)\obj\LLIntOffsetsExtractor"
+ IntermediateDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ ConfigurationType="1"
+ InheritedPropertySheets=".\LLIntOffsetsExtractorProduction.vsprops"
+ CharacterSet="1"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release_Cairo_CFLite|Win32"
+ OutputDirectory="$(ConfigurationBuildDir)\obj\LLIntOffsetsExtractor"
+ IntermediateDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ ConfigurationType="1"
+ InheritedPropertySheets=".\LLIntOffsetsExtractorReleaseCairoCFLite.vsprops"
+ CharacterSet="1"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release_PGO|Win32"
+ OutputDirectory="$(ConfigurationBuildDir)\obj\LLIntOffsetsExtractor"
+ IntermediateDirectory="$(ConfigurationBuildDir)\obj\$(ProjectName)"
+ ConfigurationType="1"
+ InheritedPropertySheets=".\LLIntOffsetsExtractorReleasePGO.vsprops"
+ CharacterSet="1"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\..\llint\LLIntOffsetsExtractor.cpp"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorCommon.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorCommon.vsprops new file mode 100644 index 000000000..6340081d9 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorCommon.vsprops @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="LLIntOffsetsExtractorCommon"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""$(ConfigurationBuildDir)\include";"$(ConfigurationBuildDir)\include\private";"$(ConfigurationBuildDir)\include\private\JavaScriptCore";"$(ConfigurationBuildDir)\obj\JavaScriptCore\DerivedSources\";../../;"../../os-win32/";../../assembler/;../../API/;../../parser/;../../heap/;../../runtime/;../../VM/;../../bytecode/;../../interpreter/;../../wtf/;../../debugger/;../../bytecompiler/;../../profiler;../../jit/;"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitLibrariesDir)\include""
+ PreprocessorDefinitions="__STD_C"
+ ForcedIncludeFiles="ICUVersion.h"
+ ForcedUsingFiles=""
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="libicuin$(LibraryConfigSuffix).lib libicuuc$(LibraryConfigSuffix).lib pthreadVC2$(LibraryConfigSuffix).lib winmm.lib pthreadVC2$(LibraryConfigSuffix).lib user32.lib WTF$(WebKitConfigSuffix).lib"
+ AdditionalLibraryDirectories=""$(IntDir)\lib""
+ SubSystem="1"
+ />
+</VisualStudioPropertySheet>
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorDebug.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorDebug.vsprops new file mode 100644 index 000000000..69c0a2738 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorDebug.vsprops @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="LLIntOffsetsExtractorDebug"
+ InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;.\LLIntOffsetsExtractorCommon.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorDebugAll.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorDebugAll.vsprops new file mode 100644 index 000000000..e508f9160 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorDebugAll.vsprops @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="LLIntOffsetsExtractorDebugAll"
+ InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;.\LLIntOffsetsExtractorCommon.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug_all.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorDebugCairoCFLite.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorDebugCairoCFLite.vsprops new file mode 100644 index 000000000..33804ca90 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorDebugCairoCFLite.vsprops @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="LLIntOffsetsExtractorDebugCairoCFLite"
+ InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug_wincairo.vsprops;.\LLIntOffsetsExtractorCommon.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorProduction.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorProduction.vsprops new file mode 100644 index 000000000..3683199fd --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorProduction.vsprops @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="LLIntOffsetsExtractorProduction"
+ InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\production.vsprops;.\LLIntOffsetsExtractorCommon.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorRelease.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorRelease.vsprops new file mode 100644 index 000000000..b2f4e872d --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorRelease.vsprops @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="LLIntOffsetsExtractorRelease"
+ InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;.\LLIntOffsetsExtractorCommon.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorReleaseCairoCFLite.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorReleaseCairoCFLite.vsprops new file mode 100644 index 000000000..4adb12216 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorReleaseCairoCFLite.vsprops @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="LLIntOffsetsExtractorReleaseCairoCFLite"
+ InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\WinCairo.vsprops;.\LLIntOffsetsExtractorCommon.vsprops"
+ >
+</VisualStudioPropertySheet>
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorReleasePGO.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorReleasePGO.vsprops new file mode 100644 index 000000000..331f96af2 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/LLIntOffsetsExtractor/LLIntOffsetsExtractorReleasePGO.vsprops @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="LLIntOffsetsExtractorReleasePGO"
+ InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\production.vsprops;.\LLIntOffsetsExtractorCommon.vsprops"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""$(ConfigurationBuildDir)\..\Production\include\private";"$(ConfigurationBuildDir)\..\Production\include\private\wtf\text""
+ />
+</VisualStudioPropertySheet>
diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj index db75c0761..7c5ebaded 100644 --- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj @@ -200,7 +200,6 @@ 0FB7F39C15ED8E4600F167B2 /* PropertyStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB7F39015ED8E3800F167B2 /* PropertyStorage.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FB7F39D15ED8E4600F167B2 /* Reject.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB7F39115ED8E3800F167B2 /* Reject.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FB7F39E15ED8E4600F167B2 /* SparseArrayValueMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB7F39215ED8E3800F167B2 /* SparseArrayValueMap.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 0FB7F39F15ED8E4600F167B2 /* SparseArrayValueMapInlineMethods.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB7F39315ED8E3800F167B2 /* SparseArrayValueMapInlineMethods.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FBC0AE71496C7C400D4FBDD /* DFGExitProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FBC0AE41496C7C100D4FBDD /* DFGExitProfile.cpp */; }; 0FBC0AE81496C7C700D4FBDD /* DFGExitProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FBC0AE51496C7C100D4FBDD /* DFGExitProfile.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FBD7E691447999600481315 /* CodeOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FBD7E671447998F00481315 /* CodeOrigin.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -971,7 +970,6 @@ 0FB7F39015ED8E3800F167B2 /* PropertyStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PropertyStorage.h; sourceTree = "<group>"; }; 0FB7F39115ED8E3800F167B2 /* Reject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reject.h; sourceTree = "<group>"; }; 0FB7F39215ED8E3800F167B2 /* SparseArrayValueMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SparseArrayValueMap.h; sourceTree = "<group>"; }; - 0FB7F39315ED8E3800F167B2 /* SparseArrayValueMapInlineMethods.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SparseArrayValueMapInlineMethods.h; sourceTree = "<group>"; }; 0FBC0AE41496C7C100D4FBDD /* DFGExitProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DFGExitProfile.cpp; sourceTree = "<group>"; }; 0FBC0AE51496C7C100D4FBDD /* DFGExitProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DFGExitProfile.h; sourceTree = "<group>"; }; 0FBD7E671447998F00481315 /* CodeOrigin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeOrigin.h; sourceTree = "<group>"; }; @@ -2057,7 +2055,6 @@ 0FB7F39015ED8E3800F167B2 /* PropertyStorage.h */, 0FB7F39115ED8E3800F167B2 /* Reject.h */, 0FB7F39215ED8E3800F167B2 /* SparseArrayValueMap.h */, - 0FB7F39315ED8E3800F167B2 /* SparseArrayValueMapInlineMethods.h */, C2D58C3315912FEE0021A844 /* GCActivityCallback.cpp */, BCF605110E203EF800B9A64D /* ArgList.cpp */, BCF605120E203EF800B9A64D /* ArgList.h */, @@ -2952,7 +2949,6 @@ 0FB7F39C15ED8E4600F167B2 /* PropertyStorage.h in Headers */, 0FB7F39D15ED8E4600F167B2 /* Reject.h in Headers */, 0FB7F39E15ED8E4600F167B2 /* SparseArrayValueMap.h in Headers */, - 0FB7F39F15ED8E4600F167B2 /* SparseArrayValueMapInlineMethods.h in Headers */, 0F0CD4C215F1A6070032F1C0 /* PutDirectIndexMode.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerARM.h b/Source/JavaScriptCore/assembler/MacroAssemblerARM.h index e3b0be9da..c4d6c92a5 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerARM.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerARM.h @@ -212,6 +212,14 @@ public: m_assembler.orrs(dest, dest, src); } + void or32(RegisterID src, AbsoluteAddress dest) + { + move(TrustedImmPtr(dest.m_ptr), ARMRegisters::S0); + load32(Address(ARMRegisters::S0), ARMRegisters::S1); + or32(src, ARMRegisters::S1); + store32(ARMRegisters::S1, ARMRegisters::S0); + } + void or32(TrustedImm32 imm, RegisterID dest) { m_assembler.orrs(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0)); diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h b/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h index d2da886c2..1dfe888d3 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h @@ -313,6 +313,14 @@ public: { m_assembler.orr(dest, dest, src); } + + void or32(RegisterID src, AbsoluteAddress dest) + { + move(TrustedImmPtr(dest.m_ptr), addressTempRegister); + load32(addressTempRegister, dataTempRegister); + or32(src, dataTempRegister); + store32(dataTempRegister, addressTempRegister); + } void or32(TrustedImm32 imm, RegisterID dest) { diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerX86.h b/Source/JavaScriptCore/assembler/MacroAssemblerX86.h index d1a4ff3c4..d46867ae3 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerX86.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerX86.h @@ -84,6 +84,11 @@ public: m_assembler.orl_im(imm.m_value, address.m_ptr); } + void or32(RegisterID reg, AbsoluteAddress address) + { + m_assembler.orl_rm(reg, address.m_ptr); + } + void sub32(TrustedImm32 imm, AbsoluteAddress address) { m_assembler.subl_im(imm.m_value, address.m_ptr); diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h b/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h index ac90516f4..c827e8ae9 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h @@ -75,6 +75,12 @@ public: or32(imm, Address(scratchRegister)); } + void or32(RegisterID reg, AbsoluteAddress address) + { + move(TrustedImmPtr(address.m_ptr), scratchRegister); + or32(reg, Address(scratchRegister)); + } + void sub32(TrustedImm32 imm, AbsoluteAddress address) { move(TrustedImmPtr(address.m_ptr), scratchRegister); diff --git a/Source/JavaScriptCore/assembler/X86Assembler.h b/Source/JavaScriptCore/assembler/X86Assembler.h index adaee4bc0..acd573049 100644 --- a/Source/JavaScriptCore/assembler/X86Assembler.h +++ b/Source/JavaScriptCore/assembler/X86Assembler.h @@ -541,6 +541,11 @@ public: m_formatter.immediate32(imm); } } + + void orl_rm(RegisterID src, const void* addr) + { + m_formatter.oneByteOp(OP_OR_EvGv, src, addr); + } #endif void subl_rr(RegisterID src, RegisterID dst) diff --git a/Source/JavaScriptCore/bytecode/ArrayProfile.cpp b/Source/JavaScriptCore/bytecode/ArrayProfile.cpp index 6b97f7806..9f4e1ce20 100644 --- a/Source/JavaScriptCore/bytecode/ArrayProfile.cpp +++ b/Source/JavaScriptCore/bytecode/ArrayProfile.cpp @@ -43,6 +43,11 @@ void ArrayProfile::computeUpdatedPrediction(OperationInProgress operation) m_lastSeenStructure = 0; } + if (hasTwoOrMoreBitsSet(m_observedArrayModes)) { + m_structureIsPolymorphic = true; + m_expectedStructure = 0; + } + if (operation == Collection && m_expectedStructure && !Heap::isMarked(m_expectedStructure)) { diff --git a/Source/JavaScriptCore/bytecode/ArrayProfile.h b/Source/JavaScriptCore/bytecode/ArrayProfile.h index 312473f3c..43818d77d 100644 --- a/Source/JavaScriptCore/bytecode/ArrayProfile.h +++ b/Source/JavaScriptCore/bytecode/ArrayProfile.h @@ -36,7 +36,7 @@ namespace JSC { class LLIntOffsetsExtractor; // This is a bitfield where each bit represents an IndexingType that we have seen. -// There are 17 indexing types (0 to 16, inclusive), so 32 bits is more than enough. +// There are 32 indexing types, so an unsigned is enough. typedef unsigned ArrayModes; #define asArrayModes(type) \ @@ -44,7 +44,7 @@ typedef unsigned ArrayModes; inline ArrayModes arrayModeFromStructure(Structure* structure) { - return asArrayModes(structure->indexingTypeIncludingHistory()); + return asArrayModes(structure->indexingType()); } class ArrayProfile { @@ -70,6 +70,7 @@ public: unsigned bytecodeOffset() const { return m_bytecodeOffset; } Structure** addressOfLastSeenStructure() { return &m_lastSeenStructure; } + ArrayModes* addressOfArrayModes() { return &m_observedArrayModes; } void observeStructure(Structure* structure) { @@ -79,7 +80,10 @@ public: void computeUpdatedPrediction(OperationInProgress operation = NoOperation); Structure* expectedStructure() const { return m_expectedStructure; } - bool structureIsPolymorphic() const { return m_structureIsPolymorphic; } + bool structureIsPolymorphic() const + { + return m_structureIsPolymorphic; + } bool hasDefiniteStructure() const { return !structureIsPolymorphic() && m_expectedStructure; diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h index 07d1e0a06..d0c969c6d 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.h +++ b/Source/JavaScriptCore/bytecode/CodeBlock.h @@ -1544,6 +1544,25 @@ namespace JSC { } #endif + inline JSValue ExecState::argumentAfterCapture(size_t argument) + { + if (argument >= argumentCount()) + return jsUndefined(); + + if (!codeBlock()) + return this[argumentOffset(argument)].jsValue(); + + if (argument >= static_cast<size_t>(codeBlock()->symbolTable()->parameterCount())) + return this[argumentOffset(argument)].jsValue(); + + const SlowArgument* slowArguments = codeBlock()->symbolTable()->slowArguments(); + if (!slowArguments || slowArguments[argument].status == SlowArgument::Normal) + return this[argumentOffset(argument)].jsValue(); + + ASSERT(slowArguments[argument].status == SlowArgument::Captured); + return this[slowArguments[argument].indexIfCaptured].jsValue(); + } + #if ENABLE(DFG_JIT) inline void DFGCodeBlocks::mark(void* candidateCodeBlock) { diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp index 055f605d2..e7a80fe2c 100644 --- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp +++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp @@ -423,18 +423,19 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, JSScope* sc } } - bool capturesAnyArgument = codeBlock->usesArguments() || codeBlock->usesEval() || m_shouldEmitDebugHooks; // May reify arguments object. - if (!capturesAnyArgument && functionBody->hasCapturedVariables()) { + bool mayReifyArgumentsObject = codeBlock->usesArguments() || codeBlock->usesEval() || m_shouldEmitDebugHooks; + bool capturesAnyArgumentByName = false; + if (functionBody->hasCapturedVariables()) { FunctionParameters& parameters = *functionBody->parameters(); for (size_t i = 0; i < parameters.size(); ++i) { if (!functionBody->captures(parameters[i])) continue; - capturesAnyArgument = true; + capturesAnyArgumentByName = true; break; } } - if (capturesAnyArgument) { + if (mayReifyArgumentsObject || capturesAnyArgumentByName) { symbolTable->setCaptureMode(SharedSymbolTable::AllOfTheThings); symbolTable->setCaptureStart(-CallFrame::offsetFor(symbolTable->parameterCountIncludingThis())); } else { @@ -442,6 +443,16 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, JSScope* sc symbolTable->setCaptureStart(m_codeBlock->m_numVars); } + if (mayReifyArgumentsObject && capturesAnyArgumentByName) { + size_t parameterCount = symbolTable->parameterCount(); + OwnArrayPtr<SlowArgument> slowArguments = adoptArrayPtr(new SlowArgument[parameterCount]); + for (size_t i = 0; i < parameterCount; ++i) { + slowArguments[i].status = SlowArgument::Captured; + slowArguments[i].indexIfCaptured = CallFrame::argumentOffset(i); + } + symbolTable->setSlowArguments(slowArguments.release()); + } + RegisterID* calleeRegister = resolveCallee(functionBody); // May push to the scope chain and/or add a captured var. const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack(); @@ -681,7 +692,7 @@ bool BytecodeGenerator::willResolveToArguments(const Identifier& ident) SymbolTableEntry entry = symbolTable().get(ident.impl()); if (entry.isNull()) return false; - + if (m_codeBlock->usesArguments() && m_codeType == FunctionCode) return true; diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp index b860a7310..153ba311c 100644 --- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp +++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp @@ -147,7 +147,13 @@ void AbstractState::initialize(Graph& graph) for (size_t i = 0; i < graph.m_mustHandleValues.size(); ++i) { AbstractValue value; value.setMostSpecific(graph.m_mustHandleValues[i]); - block->valuesAtHead.operand(graph.m_mustHandleValues.operandForIndex(i)).merge(value); + int operand = graph.m_mustHandleValues.operandForIndex(i); + block->valuesAtHead.operand(operand).merge(value); +#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) + dataLog(" Initializing Block #%u, operand r%d, to ", blockIndex, operand); + block->valuesAtHead.operand(operand).dump(WTF::dataFile()); + dataLog("\n"); +#endif } block->cfaShouldRevisit = true; } @@ -1093,14 +1099,21 @@ bool AbstractState::execute(unsigned indexInBlock) break; case NewArray: - case NewArrayBuffer: - node.setCanExit(false); + node.setCanExit(true); forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructure()); m_haveStructures = true; break; + case NewArrayBuffer: + // Unless we're having a bad time, this node can change its mind about what structure + // it uses. + node.setCanExit(false); + forNode(nodeIndex).set(SpecArray); + break; + case NewArrayWithSize: - speculateInt32Unary(node); + node.setCanExit(true); + forNode(node.child1()).filter(SpecInt32); forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructure()); m_haveStructures = true; break; @@ -1293,20 +1306,6 @@ bool AbstractState::execute(unsigned indexInBlock) !value.m_currentKnownStructure.isSubsetOf(set) || !isCellSpeculation(value.m_type)); value.filter(set); - // This is likely to be unnecessary, but it's conservative, and that's a good thing. - // This is trying to avoid situations where the CFA proves that this structure check - // must fail due to a future structure proof. We have two options at that point. We - // can either compile all subsequent code as we would otherwise, or we can ensure - // that the subsequent code is never reachable. The former is correct because the - // Proof Is Infallible (TM) -- hence even if we don't force the subsequent code to - // be unreachable, it must be unreachable nonetheless. But imagine what would happen - // if the proof was borked. In the former case, we'd get really bizarre bugs where - // we assumed that the structure of this object was known even though it wasn't. In - // the latter case, we'd have a slight performance pathology because this would be - // turned into an OSR exit unnecessarily. Which would you rather have? - if (value.m_currentKnownStructure.isClear() - || value.m_futurePossibleStructure.isClear()) - m_isValid = false; m_haveStructures = true; break; } @@ -1325,10 +1324,6 @@ bool AbstractState::execute(unsigned indexInBlock) ASSERT(value.isClear() || isCellSpeculation(value.m_type)); // Value could be clear if we've proven must-exit due to a speculation statically known to be bad. value.filter(node.structure()); - // See comment in CheckStructure for why this is here. - if (value.m_currentKnownStructure.isClear() - || value.m_futurePossibleStructure.isClear()) - m_isValid = false; m_haveStructures = true; node.setCanExit(true); break; @@ -1337,9 +1332,11 @@ bool AbstractState::execute(unsigned indexInBlock) case PutStructure: case PhantomPutStructure: node.setCanExit(false); - clobberStructures(indexInBlock); - forNode(node.child1()).set(node.structureTransitionData().newStructure); - m_haveStructures = true; + if (!forNode(node.child1()).m_currentKnownStructure.isClear()) { + clobberStructures(indexInBlock); + forNode(node.child1()).set(node.structureTransitionData().newStructure); + m_haveStructures = true; + } break; case GetButterfly: case AllocatePropertyStorage: diff --git a/Source/JavaScriptCore/dfg/DFGArrayMode.cpp b/Source/JavaScriptCore/dfg/DFGArrayMode.cpp index eda578205..fe2a05b8b 100644 --- a/Source/JavaScriptCore/dfg/DFGArrayMode.cpp +++ b/Source/JavaScriptCore/dfg/DFGArrayMode.cpp @@ -42,10 +42,16 @@ Array::Mode fromObserved(ArrayModes modes, bool makeSafe) return Array::Undecided; case asArrayModes(NonArrayWithArrayStorage): return makeSafe ? Array::ArrayStorageOutOfBounds : Array::ArrayStorage; + case asArrayModes(NonArrayWithSlowPutArrayStorage): + return Array::SlowPutArrayStorage; case asArrayModes(ArrayWithArrayStorage): return makeSafe ? Array::ArrayWithArrayStorageOutOfBounds : Array::ArrayWithArrayStorage; + case asArrayModes(ArrayWithSlowPutArrayStorage): + return Array::ArrayWithSlowPutArrayStorage; case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage): return makeSafe ? Array::PossiblyArrayWithArrayStorageOutOfBounds : Array::PossiblyArrayWithArrayStorage; + case asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage): + return Array::PossiblyArrayWithSlowPutArrayStorage; default: // We know that this is possibly a kind of array for which, though there is no // useful data in the array profile, we may be able to extract useful data from @@ -124,15 +130,29 @@ bool modeAlreadyChecked(AbstractValue& value, Array::Mode arrayMode) case Array::String: return isStringSpeculation(value.m_type); - case NON_ARRAY_ARRAY_STORAGE_MODES: + case Array::ArrayStorage: + case Array::ArrayStorageOutOfBounds: + case Array::PossiblyArrayWithArrayStorage: + case Array::PossiblyArrayWithArrayStorageOutOfBounds: return value.m_currentKnownStructure.hasSingleton() && (value.m_currentKnownStructure.singleton()->indexingType() & HasArrayStorage); - - case ARRAY_WITH_ARRAY_STORAGE_MODES: + + case Array::SlowPutArrayStorage: + case Array::PossiblyArrayWithSlowPutArrayStorage: + return value.m_currentKnownStructure.hasSingleton() + && (value.m_currentKnownStructure.singleton()->indexingType() & HasSlowPutArrayStorage); + + case Array::ArrayWithArrayStorage: + case Array::ArrayWithArrayStorageOutOfBounds: return value.m_currentKnownStructure.hasSingleton() && (value.m_currentKnownStructure.singleton()->indexingType() & HasArrayStorage) && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray); + case Array::ArrayWithSlowPutArrayStorage: + return value.m_currentKnownStructure.hasSingleton() + && (value.m_currentKnownStructure.singleton()->indexingType() & HasSlowPutArrayStorage) + && (value.m_currentKnownStructure.singleton()->indexingType() & IsArray); + case Array::Arguments: return isArgumentsSpeculation(value.m_type); @@ -184,14 +204,20 @@ const char* modeToString(Array::Mode mode) return "String"; case Array::ArrayStorage: return "ArrayStorage"; + case Array::SlowPutArrayStorage: + return "SlowPutArrayStorage"; case Array::ArrayStorageOutOfBounds: return "ArrayStorageOutOfBounds"; case Array::ArrayWithArrayStorage: return "ArrayWithArrayStorage"; + case Array::ArrayWithSlowPutArrayStorage: + return "ArrayWithSlowPutArrayStorage"; case Array::ArrayWithArrayStorageOutOfBounds: return "ArrayWithArrayStorageOutOfBounds"; case Array::PossiblyArrayWithArrayStorage: return "PossiblyArrayWithArrayStorage"; + case Array::PossiblyArrayWithSlowPutArrayStorage: + return "PossiblyArrayWithSlowPutArrayStorage"; case Array::PossiblyArrayWithArrayStorageOutOfBounds: return "PossiblyArrayWithArrayStorageOutOfBounds"; case Array::Arguments: diff --git a/Source/JavaScriptCore/dfg/DFGArrayMode.h b/Source/JavaScriptCore/dfg/DFGArrayMode.h index 2eb009be0..cc8b1b809 100644 --- a/Source/JavaScriptCore/dfg/DFGArrayMode.h +++ b/Source/JavaScriptCore/dfg/DFGArrayMode.h @@ -47,10 +47,13 @@ enum Mode { Generic, String, ArrayStorage, + SlowPutArrayStorage, ArrayStorageOutOfBounds, ArrayWithArrayStorage, + ArrayWithSlowPutArrayStorage, ArrayWithArrayStorageOutOfBounds, PossiblyArrayWithArrayStorage, + PossiblyArrayWithSlowPutArrayStorage, PossiblyArrayWithArrayStorageOutOfBounds, Arguments, Int8Array, @@ -70,11 +73,14 @@ enum Mode { // have the word "ArrayStorage" in them. #define NON_ARRAY_ARRAY_STORAGE_MODES \ Array::ArrayStorage: \ + case Array::SlowPutArrayStorage: \ case Array::ArrayStorageOutOfBounds: \ case Array::PossiblyArrayWithArrayStorage: \ + case Array::PossiblyArrayWithSlowPutArrayStorage: \ case Array::PossiblyArrayWithArrayStorageOutOfBounds #define ARRAY_WITH_ARRAY_STORAGE_MODES \ Array::ArrayWithArrayStorage: \ + case Array::ArrayWithSlowPutArrayStorage: \ case Array::ArrayWithArrayStorageOutOfBounds #define ALL_ARRAY_STORAGE_MODES \ NON_ARRAY_ARRAY_STORAGE_MODES: \ @@ -83,8 +89,13 @@ enum Mode { Array::ArrayStorage: \ case Array::ArrayWithArrayStorage: \ case Array::PossiblyArrayWithArrayStorage +#define SLOW_PUT_ARRAY_STORAGE_MODES \ + Array::SlowPutArrayStorage: \ + case Array::ArrayWithSlowPutArrayStorage: \ + case Array::PossiblyArrayWithSlowPutArrayStorage #define OUT_OF_BOUNDS_ARRAY_STORAGE_MODES \ - Array::ArrayStorageOutOfBounds: \ + SLOW_PUT_ARRAY_STORAGE_MODES: \ + case Array::ArrayStorageOutOfBounds: \ case Array::ArrayWithArrayStorageOutOfBounds: \ case Array::PossiblyArrayWithArrayStorageOutOfBounds @@ -128,6 +139,16 @@ inline bool isInBoundsAccess(Array::Mode arrayMode) } } +inline bool isSlowPutAccess(Array::Mode arrayMode) +{ + switch (arrayMode) { + case SLOW_PUT_ARRAY_STORAGE_MODES: + return true; + default: + return false; + } +} + inline bool canCSEStorage(Array::Mode arrayMode) { switch (arrayMode) { diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp index 19a389218..67ae7bf03 100644 --- a/Source/JavaScriptCore/dfg/DFGOperations.cpp +++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp @@ -1178,7 +1178,7 @@ void DFG_OPERATION operationTearOffArguments(ExecState* exec, JSCell* argumentsC { ASSERT(exec->codeBlock()->usesArguments()); if (activationCell) { - jsCast<Arguments*>(argumentsCell)->didTearOffActivation(exec->globalData(), jsCast<JSActivation*>(activationCell)); + jsCast<Arguments*>(argumentsCell)->didTearOffActivation(exec, jsCast<JSActivation*>(activationCell)); return; } jsCast<Arguments*>(argumentsCell)->tearOff(exec); diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp index b1f3212f9..07cb11032 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp @@ -324,7 +324,8 @@ void SpeculativeJIT::checkArray(Node& node) m_jit.branchTest8( MacroAssembler::Zero, MacroAssembler::Address(temp.gpr(), Structure::indexingTypeOffset()), - MacroAssembler::TrustedImm32(HasArrayStorage))); + MacroAssembler::TrustedImm32( + isSlowPutAccess(node.arrayMode()) ? HasSlowPutArrayStorage : HasArrayStorage))); noResult(m_compileIndex); return; @@ -345,7 +346,8 @@ void SpeculativeJIT::checkArray(Node& node) speculationCheck( Uncountable, JSValueRegs(), NoNode, m_jit.branchTest32( - MacroAssembler::Zero, tempGPR, MacroAssembler::TrustedImm32(HasArrayStorage))); + MacroAssembler::Zero, tempGPR, MacroAssembler::TrustedImm32( + isSlowPutAccess(node.arrayMode()) ? HasSlowPutArrayStorage : HasArrayStorage))); noResult(m_compileIndex); return; @@ -3055,28 +3057,24 @@ void SpeculativeJIT::compileGetByValOnArguments(Node& node) ASSERT(modeAlreadyChecked(m_state.forNode(node.child1()), Array::Arguments)); - m_jit.loadPtr( - MacroAssembler::Address(baseReg, Arguments::offsetOfData()), - scratchReg); - // Two really lame checks. speculationCheck( Uncountable, JSValueSource(), NoNode, m_jit.branchPtr( MacroAssembler::AboveOrEqual, propertyReg, - MacroAssembler::Address(scratchReg, OBJECT_OFFSETOF(ArgumentsData, numArguments)))); + MacroAssembler::Address(baseReg, OBJECT_OFFSETOF(Arguments, m_numArguments)))); speculationCheck( Uncountable, JSValueSource(), NoNode, m_jit.branchTestPtr( MacroAssembler::NonZero, MacroAssembler::Address( - scratchReg, OBJECT_OFFSETOF(ArgumentsData, deletedArguments)))); + baseReg, OBJECT_OFFSETOF(Arguments, m_slowArguments)))); m_jit.move(propertyReg, resultReg); m_jit.neg32(resultReg); m_jit.signExtend32ToPtr(resultReg, resultReg); m_jit.loadPtr( - MacroAssembler::Address(scratchReg, OBJECT_OFFSETOF(ArgumentsData, registers)), + MacroAssembler::Address(baseReg, OBJECT_OFFSETOF(Arguments, m_registers)), scratchReg); #if USE(JSVALUE32_64) @@ -3116,18 +3114,14 @@ void SpeculativeJIT::compileGetArgumentsLength(Node& node) ASSERT(modeAlreadyChecked(m_state.forNode(node.child1()), Array::Arguments)); - m_jit.loadPtr( - MacroAssembler::Address(baseReg, Arguments::offsetOfData()), - resultReg); - speculationCheck( Uncountable, JSValueSource(), NoNode, m_jit.branchTest8( MacroAssembler::NonZero, - MacroAssembler::Address(resultReg, OBJECT_OFFSETOF(ArgumentsData, overrodeLength)))); + MacroAssembler::Address(baseReg, OBJECT_OFFSETOF(Arguments, m_overrodeLength)))); m_jit.load32( - MacroAssembler::Address(resultReg, OBJECT_OFFSETOF(ArgumentsData, numArguments)), + MacroAssembler::Address(baseReg, OBJECT_OFFSETOF(Arguments, m_numArguments)), resultReg); integerResult(resultReg, m_compileIndex); } diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp index f40db37a6..85e32ddb9 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp @@ -2741,25 +2741,37 @@ void SpeculativeJIT::compile(Node& node) // Check if we're writing to a hole; if so increment m_numValuesInVector. MacroAssembler::Jump notHoleValue = m_jit.branch32(MacroAssembler::NotEqual, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag)); - m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); - - // If we're writing to a hole we might be growing the array; - MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset())); - m_jit.add32(TrustedImm32(1), propertyReg); - m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset())); - m_jit.sub32(TrustedImm32(1), propertyReg); - - lengthDoesNotNeedUpdate.link(&m_jit); + MacroAssembler::Jump isHoleValue; + if (isSlowPutAccess(arrayMode)) { + // This is sort of strange. If we wanted to optimize this code path, we would invert + // the above branch. But it's simply not worth it since this only happens if we're + // already having a bad time. + isHoleValue = m_jit.jump(); + } else { + m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); + + // If we're writing to a hole we might be growing the array; + MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset())); + m_jit.add32(TrustedImm32(1), propertyReg); + m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset())); + m_jit.sub32(TrustedImm32(1), propertyReg); + + lengthDoesNotNeedUpdate.link(&m_jit); + } notHoleValue.link(&m_jit); // Store the value to the array. m_jit.store32(valueTagReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag))); m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload))); - if (!isInBoundsAccess(node.arrayMode())) { + if (!isInBoundsAccess(arrayMode)) { + MacroAssembler::JumpList slowCases; + slowCases.append(beyondArrayBounds); + if (isSlowPutAccess(arrayMode)) + slowCases.append(isHoleValue); addSlowPathGenerator( slowPathCall( - beyondArrayBounds, this, + slowCases, this, m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict, NoResult, baseReg, propertyReg, valueTagReg, valuePayloadReg)); } @@ -3128,13 +3140,17 @@ void SpeculativeJIT::compile(Node& node) } case NewArray: { + JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node.codeOrigin); + if (!globalObject->isHavingABadTime()) + globalObject->havingABadTimeWatchpoint()->add(speculationWatchpoint()); + if (!node.numChildren()) { flushRegisters(); GPRResult result(this); GPRResult2 resultTagIgnored(this); callOperation( operationNewEmptyArray, resultTagIgnored.gpr(), result.gpr(), - m_jit.graph().globalObjectFor(node.codeOrigin)->arrayStructure()); + globalObject->arrayStructure()); cellResult(result.gpr(), m_compileIndex); break; } @@ -3167,8 +3183,7 @@ void SpeculativeJIT::compile(Node& node) GPRResult2 resultTag(this); callOperation( - operationNewArray, resultTag.gpr(), resultPayload.gpr(), - m_jit.graph().globalObjectFor(node.codeOrigin)->arrayStructure(), + operationNewArray, resultTag.gpr(), resultPayload.gpr(), globalObject->arrayStructure(), static_cast<void *>(buffer), node.numChildren()); if (scratchSize) { @@ -3184,6 +3199,10 @@ void SpeculativeJIT::compile(Node& node) } case NewArrayWithSize: { + JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node.codeOrigin); + if (!globalObject->isHavingABadTime()) + globalObject->havingABadTimeWatchpoint()->add(speculationWatchpoint()); + SpeculateStrictInt32Operand size(this, node.child1()); GPRReg sizeGPR = size.gpr(); flushRegisters(); @@ -3191,7 +3210,7 @@ void SpeculativeJIT::compile(Node& node) GPRResult2 resultTagIgnored(this); callOperation( operationNewArrayWithSize, resultTagIgnored.gpr(), result.gpr(), - m_jit.graph().globalObjectFor(node.codeOrigin)->arrayStructure(), sizeGPR); + globalObject->arrayStructure(), sizeGPR); cellResult(result.gpr(), m_compileIndex); break; } diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp index aa5fe6773..f050af699 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp @@ -2760,24 +2760,36 @@ void SpeculativeJIT::compile(Node& node) // Check if we're writing to a hole; if so increment m_numValuesInVector. MacroAssembler::Jump notHoleValue = m_jit.branchTestPtr(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))); - m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); - - // If we're writing to a hole we might be growing the array; - MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset())); - m_jit.add32(TrustedImm32(1), propertyReg); - m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset())); - m_jit.sub32(TrustedImm32(1), propertyReg); - - lengthDoesNotNeedUpdate.link(&m_jit); + MacroAssembler::Jump isHoleValue; + if (isSlowPutAccess(arrayMode)) { + // This is sort of strange. If we wanted to optimize this code path, we would invert + // the above branch. But it's simply not worth it since this only happens if we're + // already having a bad time. + isHoleValue = m_jit.jump(); + } else { + m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); + + // If we're writing to a hole we might be growing the array; + MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset())); + m_jit.add32(TrustedImm32(1), propertyReg); + m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset())); + m_jit.sub32(TrustedImm32(1), propertyReg); + + lengthDoesNotNeedUpdate.link(&m_jit); + } notHoleValue.link(&m_jit); // Store the value to the array. m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))); if (!isInBoundsAccess(arrayMode)) { + MacroAssembler::JumpList slowCases; + slowCases.append(beyondArrayBounds); + if (isSlowPutAccess(arrayMode)) + slowCases.append(isHoleValue); addSlowPathGenerator( slowPathCall( - beyondArrayBounds, this, + slowCases, this, m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict, NoResult, baseReg, propertyReg, valueReg)); } @@ -2798,28 +2810,24 @@ void SpeculativeJIT::compile(Node& node) if (!m_compileOkay) return; - m_jit.loadPtr( - MacroAssembler::Address(baseReg, Arguments::offsetOfData()), - scratchReg); - // Two really lame checks. speculationCheck( Uncountable, JSValueSource(), NoNode, m_jit.branchPtr( MacroAssembler::AboveOrEqual, propertyReg, - MacroAssembler::Address(scratchReg, OBJECT_OFFSETOF(ArgumentsData, numArguments)))); + MacroAssembler::Address(baseReg, OBJECT_OFFSETOF(Arguments, m_numArguments)))); speculationCheck( Uncountable, JSValueSource(), NoNode, m_jit.branchTestPtr( MacroAssembler::NonZero, MacroAssembler::Address( - scratchReg, OBJECT_OFFSETOF(ArgumentsData, deletedArguments)))); + baseReg, OBJECT_OFFSETOF(Arguments, m_slowArguments)))); m_jit.move(propertyReg, scratch2Reg); m_jit.neg32(scratch2Reg); m_jit.signExtend32ToPtr(scratch2Reg, scratch2Reg); m_jit.loadPtr( - MacroAssembler::Address(scratchReg, OBJECT_OFFSETOF(ArgumentsData, registers)), + MacroAssembler::Address(baseReg, OBJECT_OFFSETOF(Arguments, m_registers)), scratchReg); m_jit.storePtr( @@ -3120,12 +3128,14 @@ void SpeculativeJIT::compile(Node& node) } case NewArray: { + JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node.codeOrigin); + if (!globalObject->isHavingABadTime()) + globalObject->havingABadTimeWatchpoint()->add(speculationWatchpoint()); + if (!node.numChildren()) { flushRegisters(); GPRResult result(this); - callOperation( - operationNewEmptyArray, result.gpr(), - m_jit.graph().globalObjectFor(node.codeOrigin)->arrayStructure()); + callOperation(operationNewEmptyArray, result.gpr(), globalObject->arrayStructure()); cellResult(result.gpr(), m_compileIndex); break; } @@ -3155,8 +3165,7 @@ void SpeculativeJIT::compile(Node& node) GPRResult result(this); callOperation( - operationNewArray, result.gpr(), - m_jit.graph().globalObjectFor(node.codeOrigin)->arrayStructure(), + operationNewArray, result.gpr(), globalObject->arrayStructure(), static_cast<void*>(buffer), node.numChildren()); if (scratchSize) { @@ -3171,11 +3180,15 @@ void SpeculativeJIT::compile(Node& node) } case NewArrayWithSize: { + JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node.codeOrigin); + if (!globalObject->isHavingABadTime()) + globalObject->havingABadTimeWatchpoint()->add(speculationWatchpoint()); + SpeculateStrictInt32Operand size(this, node.child1()); GPRReg sizeGPR = size.gpr(); flushRegisters(); GPRResult result(this); - callOperation(operationNewArrayWithSize, result.gpr(), m_jit.graph().globalObjectFor(node.codeOrigin)->arrayStructure(), sizeGPR); + callOperation(operationNewArrayWithSize, result.gpr(), globalObject->arrayStructure(), sizeGPR); cellResult(result.gpr(), m_compileIndex); break; } diff --git a/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp b/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp index f6fe127a3..0838bb7e5 100644 --- a/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp @@ -67,7 +67,8 @@ public: if (!node.shouldGenerate()) continue; switch (node.op()) { - case CheckStructure: { + case CheckStructure: + case StructureTransitionWatchpoint: { Node& child = m_graph[node.child1()]; if (child.op() != GetLocal) break; @@ -91,7 +92,6 @@ public: case GetByOffset: case PutByOffset: case PutStructure: - case StructureTransitionWatchpoint: case AllocatePropertyStorage: case ReallocatePropertyStorage: case GetButterfly: @@ -105,6 +105,40 @@ public: // Don't count these uses. break; + case SetLocal: { + // Find all uses of the source of the SetLocal. If any of them are a + // kind of CheckStructure, then we should notice them to ensure that + // we're not hoisting a check that would contravene checks that are + // already being performed. + VariableAccessData* variable = node.variableAccessData(); + if (variable->isCaptured() || variable->structureCheckHoistingFailed()) + break; + if (!isCellSpeculation(variable->prediction())) + break; + NodeIndex source = node.child1().index(); + for (unsigned subIndexInBlock = 0; subIndexInBlock < block->size(); ++subIndexInBlock) { + NodeIndex subNodeIndex = block->at(subIndexInBlock); + Node& subNode = m_graph[subNodeIndex]; + if (!subNode.shouldGenerate()) + continue; + switch (subNode.op()) { + case CheckStructure: + case StructureTransitionWatchpoint: { + if (subNode.child1().index() != source) + break; + + noticeStructureCheck(variable, subNode.structureSet()); + break; + } + default: + break; + } + } + + m_graph.vote(node, VoteOther); + break; + } + default: m_graph.vote(node, VoteOther); break; diff --git a/Source/JavaScriptCore/interpreter/CallFrame.h b/Source/JavaScriptCore/interpreter/CallFrame.h index 94b37bfc3..da1222ac9 100644 --- a/Source/JavaScriptCore/interpreter/CallFrame.h +++ b/Source/JavaScriptCore/interpreter/CallFrame.h @@ -187,7 +187,7 @@ namespace JSC { // Read a register for a non-constant Register& uncheckedR(int); - // Access to arguments. + // Access to arguments as passed. (After capture, arguments may move to a different location.) size_t argumentCount() const { return argumentCountIncludingThis() - 1; } size_t argumentCountIncludingThis() const { return this[RegisterFile::ArgumentCount].payload(); } static int argumentOffset(int argument) { return s_firstArgumentOffset - argument; } @@ -208,6 +208,8 @@ namespace JSC { JSValue thisValue() { return this[thisArgumentOffset()].jsValue(); } void setThisValue(JSValue value) { this[thisArgumentOffset()] = value; } + JSValue argumentAfterCapture(size_t argument); + static int offsetFor(size_t argumentCountIncludingThis) { return argumentCountIncludingThis + RegisterFile::CallFrameHeaderSize; } // FIXME: Remove these. diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp index 739d6022f..ef6cbd5a6 100644 --- a/Source/JavaScriptCore/interpreter/Interpreter.cpp +++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp @@ -473,7 +473,7 @@ NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue ex if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->usesArguments()) { if (JSValue arguments = callFrame->uncheckedR(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue()) { if (activation) - jsCast<Arguments*>(arguments)->didTearOffActivation(callFrame->globalData(), jsCast<JSActivation*>(activation)); + jsCast<Arguments*>(arguments)->didTearOffActivation(callFrame, jsCast<JSActivation*>(activation)); else jsCast<Arguments*>(arguments)->tearOff(callFrame); } @@ -3610,8 +3610,8 @@ skip_id_custom_self: uint32_t i = subscript.asUInt32(); if (isJSArray(baseValue)) { JSArray* jsArray = asArray(baseValue); - if (jsArray->canGetIndex(i)) - result = jsArray->getIndex(i); + if (jsArray->canGetIndexQuickly(i)) + result = jsArray->getIndexQuickly(i); else result = jsArray->JSArray::get(callFrame, i); } else if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) @@ -3652,8 +3652,8 @@ skip_id_custom_self: uint32_t i = subscript.asUInt32(); if (isJSArray(baseValue)) { JSArray* jsArray = asArray(baseValue); - if (jsArray->canSetIndex(i)) - jsArray->setIndex(*globalData, i, callFrame->r(value).jsValue()); + if (jsArray->canSetIndexQuickly(i)) + jsArray->setIndexQuickly(*globalData, i, callFrame->r(value).jsValue()); else jsArray->JSArray::putByIndex(jsArray, callFrame, i, callFrame->r(value).jsValue(), codeBlock->isStrictMode()); } else @@ -4508,7 +4508,7 @@ skip_id_custom_self: ASSERT(codeBlock->usesArguments()); if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue()) { if (JSValue activationValue = callFrame->r(activation).jsValue()) - asArguments(argumentsValue)->didTearOffActivation(callFrame->globalData(), asActivation(activationValue)); + asArguments(argumentsValue)->didTearOffActivation(callFrame, asActivation(activationValue)); else asArguments(argumentsValue)->tearOff(callFrame); } @@ -5012,7 +5012,7 @@ skip_id_custom_self: accessor->setGetter(callFrame->globalData(), asObject(getter)); if (!setter.isUndefined()) accessor->setSetter(callFrame->globalData(), asObject(setter)); - baseObj->putDirectAccessor(callFrame->globalData(), ident, accessor, Accessor); + baseObj->putDirectAccessor(callFrame, ident, accessor, Accessor); vPC += OPCODE_LENGTH(op_put_getter_setter); NEXT_INSTRUCTION(); diff --git a/Source/JavaScriptCore/jit/JIT.h b/Source/JavaScriptCore/jit/JIT.h index ce70b40a7..ac7c8765b 100644 --- a/Source/JavaScriptCore/jit/JIT.h +++ b/Source/JavaScriptCore/jit/JIT.h @@ -437,7 +437,7 @@ namespace JSC { template<typename ClassType, bool destructor, typename StructureType> void emitAllocateBasicJSObject(StructureType, RegisterID result, RegisterID storagePtr); void emitAllocateBasicStorage(size_t, ptrdiff_t offsetFromBase, RegisterID result); template<typename T> void emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID storagePtr); - void emitAllocateJSArray(unsigned valuesRegister, unsigned length, RegisterID cellResult, RegisterID storageResult, RegisterID storagePtr); + void emitAllocateJSArray(unsigned valuesRegister, unsigned length, RegisterID cellResult, RegisterID storageResult, RegisterID storagePtr, RegisterID scratch); #if ENABLE(VALUE_PROFILER) // This assumes that the value to profile is in regT0 and that regT3 is available for @@ -449,6 +449,8 @@ namespace JSC { void emitValueProfilingSite(unsigned) { } void emitValueProfilingSite() { } #endif + void emitArrayProfilingSite(RegisterID structureAndIndexingType, RegisterID scratch, ArrayProfile*); + void emitArrayProfilingSiteForBytecodeIndex(RegisterID structureAndIndexingType, RegisterID scratch, unsigned bytecodeIndex); enum FinalObjectMode { MayBeFinal, KnownNotFinal }; diff --git a/Source/JavaScriptCore/jit/JITInlineMethods.h b/Source/JavaScriptCore/jit/JITInlineMethods.h index 35ac44b23..302e109ca 100644 --- a/Source/JavaScriptCore/jit/JITInlineMethods.h +++ b/Source/JavaScriptCore/jit/JITInlineMethods.h @@ -443,7 +443,7 @@ inline void JIT::emitAllocateBasicStorage(size_t size, ptrdiff_t offsetFromBase, subPtr(TrustedImm32(size - offsetFromBase), result); } -inline void JIT::emitAllocateJSArray(unsigned valuesRegister, unsigned length, RegisterID cellResult, RegisterID storageResult, RegisterID storagePtr) +inline void JIT::emitAllocateJSArray(unsigned valuesRegister, unsigned length, RegisterID cellResult, RegisterID storageResult, RegisterID storagePtr, RegisterID scratch) { unsigned initialLength = std::max(length, 4U); size_t initialStorage = Butterfly::totalSize(0, 0, true, ArrayStorage::sizeFor(initialLength)); @@ -453,7 +453,8 @@ inline void JIT::emitAllocateJSArray(unsigned valuesRegister, unsigned length, R emitAllocateBasicStorage(initialStorage, sizeof(IndexingHeader), storageResult); // Allocate the cell for the array. - emitAllocateBasicJSObject<JSArray, false>(TrustedImmPtr(m_codeBlock->globalObject()->arrayStructure()), cellResult, storagePtr); + loadPtr(m_codeBlock->globalObject()->addressOfArrayStructure(), scratch); + emitAllocateBasicJSObject<JSArray, false>(scratch, cellResult, storagePtr); // Store all the necessary info in the ArrayStorage. store32(Imm32(length), Address(storageResult, ArrayStorage::lengthOffset())); @@ -529,7 +530,31 @@ inline void JIT::emitValueProfilingSite() { emitValueProfilingSite(m_bytecodeOffset); } +#endif // ENABLE(VALUE_PROFILER) + +inline void JIT::emitArrayProfilingSite(RegisterID structureAndIndexingType, RegisterID scratch, ArrayProfile* arrayProfile) +{ + RegisterID structure = structureAndIndexingType; + RegisterID indexingType = structureAndIndexingType; + + if (canBeOptimized()) { + storePtr(structure, arrayProfile->addressOfLastSeenStructure()); + load8(Address(structure, Structure::indexingTypeOffset()), indexingType); + move(TrustedImm32(1), scratch); + lshift32(indexingType, scratch); + or32(scratch, AbsoluteAddress(arrayProfile->addressOfArrayModes())); + } else + load8(Address(structure, Structure::indexingTypeOffset()), indexingType); +} + +inline void JIT::emitArrayProfilingSiteForBytecodeIndex(RegisterID structureAndIndexingType, RegisterID scratch, unsigned bytecodeIndex) +{ +#if ENABLE(VALUE_PROFILER) + emitArrayProfilingSite(structureAndIndexingType, scratch, m_codeBlock->getOrAddArrayProfile(bytecodeIndex)); +#else + emitArrayProfilingSite(structureAndIndexingType, scratch, 0); #endif +} #if USE(JSVALUE32_64) diff --git a/Source/JavaScriptCore/jit/JITOpcodes.cpp b/Source/JavaScriptCore/jit/JITOpcodes.cpp index 486be6bf9..642aabb2a 100644 --- a/Source/JavaScriptCore/jit/JITOpcodes.cpp +++ b/Source/JavaScriptCore/jit/JITOpcodes.cpp @@ -1676,7 +1676,7 @@ void JIT::emit_op_new_array(Instruction* currentInstruction) int dst = currentInstruction[1].u.operand; int values = currentInstruction[2].u.operand; - emitAllocateJSArray(values, length, regT0, regT1, regT2); + emitAllocateJSArray(values, length, regT0, regT1, regT2, regT3); emitStoreCell(dst, regT0); } diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp index bca68f0b4..bbc289838 100644 --- a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp +++ b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp @@ -111,10 +111,8 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction) emitJumpSlowCaseIfNotJSCell(regT0, base); loadPtr(Address(regT0, JSCell::structureOffset()), regT2); -#if ENABLE(VALUE_PROFILER) - storePtr(regT2, currentInstruction[4].u.arrayProfile->addressOfLastSeenStructure()); -#endif - addSlowCase(branchTest8(Zero, Address(regT2, Structure::indexingTypeOffset()), TrustedImm32(HasArrayStorage))); + emitArrayProfilingSite(regT2, regT3, currentInstruction[4].u.arrayProfile); + addSlowCase(branchTest32(Zero, regT2, TrustedImm32(HasArrayStorage))); loadPtr(Address(regT0, JSObject::butterflyOffset()), regT2); addSlowCase(branch32(AboveOrEqual, regT1, Address(regT2, ArrayStorage::vectorLengthOffset()))); @@ -236,10 +234,8 @@ void JIT::emit_op_put_by_val(Instruction* currentInstruction) zeroExtend32ToPtr(regT1, regT1); emitJumpSlowCaseIfNotJSCell(regT0, base); loadPtr(Address(regT0, JSCell::structureOffset()), regT2); -#if ENABLE(VALUE_PROFILER) - storePtr(regT2, currentInstruction[4].u.arrayProfile->addressOfLastSeenStructure()); -#endif - addSlowCase(branchTest8(Zero, Address(regT2, Structure::indexingTypeOffset()), TrustedImm32(HasArrayStorage))); + emitArrayProfilingSite(regT2, regT3, currentInstruction[4].u.arrayProfile); + addSlowCase(branchTest32(Zero, regT2, TrustedImm32(HasArrayStorage))); loadPtr(Address(regT0, JSObject::butterflyOffset()), regT2); addSlowCase(branch32(AboveOrEqual, regT1, Address(regT2, ArrayStorage::vectorLengthOffset()))); @@ -656,13 +652,10 @@ void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress) StructureStubInfo* stubInfo = &m_codeBlock->getStubInfo(returnAddress); // Check eax is an array - loadPtr(Address(regT0, JSCell::structureOffset()), regT3); -#if ENABLE(VALUE_PROFILER) - storePtr(regT3, m_codeBlock->getOrAddArrayProfile(stubInfo->bytecodeIndex)->addressOfLastSeenStructure()); -#endif - load8(Address(regT3, Structure::indexingTypeOffset()), regT3); - Jump failureCases1 = branchTest32(Zero, regT3, TrustedImm32(IsArray)); - Jump failureCases2 = branchTest32(Zero, regT3, TrustedImm32(HasArrayStorage)); + loadPtr(Address(regT0, JSCell::structureOffset()), regT2); + emitArrayProfilingSiteForBytecodeIndex(regT2, regT1, stubInfo->bytecodeIndex); + Jump failureCases1 = branchTest32(Zero, regT2, TrustedImm32(IsArray)); + Jump failureCases2 = branchTest32(Zero, regT2, TrustedImm32(HasArrayStorage)); // Checks out okay! - get the length from the storage loadPtr(Address(regT0, JSObject::butterflyOffset()), regT3); diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp index 04d7c3815..1692f33c3 100644 --- a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp +++ b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp @@ -210,10 +210,8 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction) addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); emitJumpSlowCaseIfNotJSCell(base, regT1); loadPtr(Address(regT0, JSCell::structureOffset()), regT1); -#if ENABLE(VALUE_PROFILER) - storePtr(regT1, currentInstruction[4].u.arrayProfile->addressOfLastSeenStructure()); -#endif - addSlowCase(branchTest8(Zero, Address(regT1, Structure::indexingTypeOffset()), TrustedImm32(HasArrayStorage))); + emitArrayProfilingSite(regT1, regT3, currentInstruction[4].u.arrayProfile); + addSlowCase(branchTest32(Zero, regT1, TrustedImm32(HasArrayStorage))); loadPtr(Address(regT0, JSObject::butterflyOffset()), regT3); addSlowCase(branch32(AboveOrEqual, regT2, Address(regT3, ArrayStorage::vectorLengthOffset()))); @@ -269,10 +267,8 @@ void JIT::emit_op_put_by_val(Instruction* currentInstruction) addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); emitJumpSlowCaseIfNotJSCell(base, regT1); loadPtr(Address(regT0, JSCell::structureOffset()), regT1); -#if ENABLE(VALUE_PROFILER) - storePtr(regT1, currentInstruction[4].u.arrayProfile->addressOfLastSeenStructure()); -#endif - addSlowCase(branchTest8(Zero, Address(regT1, Structure::indexingTypeOffset()), TrustedImm32(HasArrayStorage))); + emitArrayProfilingSite(regT1, regT3, currentInstruction[4].u.arrayProfile); + addSlowCase(branchTest32(Zero, regT1, TrustedImm32(HasArrayStorage))); loadPtr(Address(regT0, JSObject::butterflyOffset()), regT3); addSlowCase(branch32(AboveOrEqual, regT2, Address(regT3, ArrayStorage::vectorLengthOffset()))); @@ -617,10 +613,7 @@ void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress) // Check for array loadPtr(Address(regT0, JSCell::structureOffset()), regT2); -#if ENABLE(VALUE_PROFILER) - storePtr(regT2, m_codeBlock->getOrAddArrayProfile(stubInfo->bytecodeIndex)->addressOfLastSeenStructure()); -#endif - load8(Address(regT2, Structure::indexingTypeOffset()), regT3); + emitArrayProfilingSiteForBytecodeIndex(regT2, regT3, stubInfo->bytecodeIndex); Jump failureCases1 = branchTest32(Zero, regT2, TrustedImm32(IsArray)); Jump failureCases2 = branchTest32(Zero, regT2, TrustedImm32(HasArrayStorage)); diff --git a/Source/JavaScriptCore/jit/JITStubs.cpp b/Source/JavaScriptCore/jit/JITStubs.cpp index 40d653b5d..e63f06cef 100644 --- a/Source/JavaScriptCore/jit/JITStubs.cpp +++ b/Source/JavaScriptCore/jit/JITStubs.cpp @@ -2323,7 +2323,7 @@ DEFINE_STUB_FUNCTION(void, op_tear_off_arguments) ASSERT(callFrame->codeBlock()->usesArguments()); Arguments* arguments = jsCast<Arguments*>(stackFrame.args[0].jsValue()); if (JSValue activationValue = stackFrame.args[1].jsValue()) { - arguments->didTearOffActivation(callFrame->globalData(), jsCast<JSActivation*>(activationValue)); + arguments->didTearOffActivation(callFrame, jsCast<JSActivation*>(activationValue)); return; } arguments->tearOff(callFrame); diff --git a/Source/JavaScriptCore/jsc.pro b/Source/JavaScriptCore/jsc.pro index f226bde40..dfd73e825 100644 --- a/Source/JavaScriptCore/jsc.pro +++ b/Source/JavaScriptCore/jsc.pro @@ -19,10 +19,6 @@ WEBKIT += javascriptcore wtf SOURCES = jsc.cpp -mac { - LIBS_PRIVATE += -framework AppKit -} - win32-* { LIBS += -ladvapi32 } diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp index b0441e80b..1ddfca37c 100644 --- a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp +++ b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp @@ -1475,7 +1475,7 @@ LLINT_SLOW_PATH_DECL(slow_path_tear_off_arguments) ASSERT(exec->codeBlock()->usesArguments()); Arguments* arguments = jsCast<Arguments*>(exec->uncheckedR(unmodifiedArgumentsRegister(pc[1].u.operand)).jsValue()); if (JSValue activationValue = LLINT_OP_C(2).jsValue()) - arguments->didTearOffActivation(globalData, jsCast<JSActivation*>(activationValue)); + arguments->didTearOffActivation(exec, jsCast<JSActivation*>(activationValue)); else arguments->tearOff(exec); LLINT_END(); diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm index 6f5460aa7..e347ccc70 100644 --- a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm +++ b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm @@ -187,6 +187,20 @@ macro slowPathForCall(advance, slowPath) end) end +macro arrayProfile(structureAndIndexingType, profile, scratch) + const structure = structureAndIndexingType + const indexingType = structureAndIndexingType + if VALUE_PROFILER + storep structure, ArrayProfile::m_lastSeenStructure[profile] + loadb Structure::m_indexingType[structure], indexingType + move 1, scratch + lshifti indexingType, scratch + ori scratch, ArrayProfile::m_observedArrayModes[profile] + else + loadb Structure::m_indexingType[structure], indexingType + end +end + macro checkSwitchToJIT(increment, action) if JIT_ENABLED loadp CodeBlock[cfr], t0 @@ -896,4 +910,3 @@ _llint_op_put_by_id_transition: # Indicate the end of LLInt. _llint_end: crash() - diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm index 0e37a4099..41926d8db 100644 --- a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm +++ b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm @@ -1176,12 +1176,9 @@ _llint_op_get_array_length: loadp 16[PC], t1 loadConstantOrVariablePayload(t0, CellTag, t3, .opGetArrayLengthSlow) loadp JSCell::m_structure[t3], t2 - if VALUE_PROFILER - storep t2, ArrayProfile::m_lastSeenStructure[t1] - end - loadb Structure::m_indexingType[t2], t1 - btiz t1, IsArray, .opGetArrayLengthSlow - btiz t1, HasArrayStorage, .opGetArrayLengthSlow + arrayProfile(t2, t1, t0) + btiz t2, IsArray, .opGetArrayLengthSlow + btiz t2, HasArrayStorage, .opGetArrayLengthSlow loadi 4[PC], t1 loadp 32[PC], t2 loadp JSObject::m_butterfly[t3], t0 @@ -1308,17 +1305,15 @@ _llint_op_put_by_id_transition_normal_out_of_line: _llint_op_get_by_val: traceExecution() loadi 8[PC], t2 - loadi 12[PC], t3 loadConstantOrVariablePayload(t2, CellTag, t0, .opGetByValSlow) + loadp JSCell::m_structure[t0], t2 + loadp 16[PC], t3 + arrayProfile(t2, t3, t1) + btiz t2, HasArrayStorage, .opGetByValSlow + loadi 12[PC], t3 loadConstantOrVariablePayload(t3, Int32Tag, t1, .opGetByValSlow) - loadp JSCell::m_structure[t0], t3 - loadp 16[PC], t2 - if VALUE_PROFILER - storep t3, ArrayProfile::m_lastSeenStructure[t2] - end - btpz Structure::m_indexingType[t3], HasArrayStorage, .opGetByValSlow loadp JSObject::m_butterfly[t0], t3 - biaeq t1, -sizeof IndexingHeader + IndexingHeader::m_vectorLength[t0], .opGetByValSlow + biaeq t1, -sizeof IndexingHeader + IndexingHeader::m_vectorLength[t3], .opGetByValSlow loadi 4[PC], t0 loadi ArrayStorage::m_vector + TagOffset[t3, t1, 8], t2 loadi ArrayStorage::m_vector + PayloadOffset[t3, t1, 8], t1 @@ -1392,14 +1387,12 @@ _llint_op_put_by_val: traceExecution() loadi 4[PC], t0 loadConstantOrVariablePayload(t0, CellTag, t1, .opPutByValSlow) + loadp JSCell::m_structure[t1], t2 + loadp 16[PC], t0 + arrayProfile(t2, t0, t3) + btiz t2, HasArrayStorage, .opPutByValSlow loadi 8[PC], t0 loadConstantOrVariablePayload(t0, Int32Tag, t2, .opPutByValSlow) - loadp JSCell::m_structure[t1], t3 - loadp 16[PC], t0 - if VALUE_PROFILER - storep t3, ArrayProfile::m_lastSeenStructure[t0] - end - btpz Structure::m_indexingType[t3], HasArrayStorage, .opPutByValSlow loadp JSObject::m_butterfly[t1], t0 biaeq t2, -sizeof IndexingHeader + IndexingHeader::m_vectorLength[t0], .opPutByValSlow bieq ArrayStorage::m_vector + TagOffset[t0, t2, 8], EmptyValueTag, .opPutByValEmpty diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm index 7dfcb6728..51a11f53f 100644 --- a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm +++ b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm @@ -1023,12 +1023,9 @@ _llint_op_get_array_length: loadp 32[PB, PC, 8], t1 loadConstantOrVariableCell(t0, t3, .opGetArrayLengthSlow) loadp JSCell::m_structure[t3], t2 - if VALUE_PROFILER - storep t2, ArrayProfile::m_lastSeenStructure[t1] - end - loadb Structure::m_indexingType[t2], t1 - btiz t1, IsArray, .opGetArrayLengthSlow - btiz t1, HasArrayStorage, .opGetArrayLengthSlow + arrayProfile(t2, t1, t0) + btiz t2, IsArray, .opGetArrayLengthSlow + btiz t2, HasArrayStorage, .opGetArrayLengthSlow loadis 8[PB, PC, 8], t1 loadp 64[PB, PC, 8], t2 loadp JSObject::m_butterfly[t3], t0 @@ -1152,16 +1149,14 @@ _llint_op_put_by_id_transition_normal_out_of_line: _llint_op_get_by_val: traceExecution() loadis 16[PB, PC, 8], t2 - loadis 24[PB, PC, 8], t3 loadConstantOrVariableCell(t2, t0, .opGetByValSlow) + loadp JSCell::m_structure[t0], t2 + loadp 32[PB, PC, 8], t3 + arrayProfile(t2, t3, t1) + loadis 24[PB, PC, 8], t3 + btiz t2, HasArrayStorage, .opGetByValSlow loadConstantOrVariableInt32(t3, t1, .opGetByValSlow) sxi2p t1, t1 - loadp JSCell::m_structure[t0], t3 - loadp 32[PB, PC, 8], t2 - if VALUE_PROFILER - storep t3, ArrayProfile::m_lastSeenStructure[t2] - end - btbz Structure::m_indexingType[t3], HasArrayStorage, .opGetByValSlow loadp JSObject::m_butterfly[t0], t3 biaeq t1, -sizeof IndexingHeader + IndexingHeader::m_vectorLength[t3], .opGetByValSlow loadis 8[PB, PC, 8], t0 @@ -1235,15 +1230,13 @@ _llint_op_put_by_val: traceExecution() loadis 8[PB, PC, 8], t0 loadConstantOrVariableCell(t0, t1, .opPutByValSlow) + loadp JSCell::m_structure[t1], t2 + loadp 32[PB, PC, 8], t0 + arrayProfile(t2, t0, t3) + btiz t2, HasArrayStorage, .opPutByValSlow loadis 16[PB, PC, 8], t0 loadConstantOrVariableInt32(t0, t2, .opPutByValSlow) sxi2p t2, t2 - loadp JSCell::m_structure[t1], t3 - loadp 32[PB, PC, 8], t0 - if VALUE_PROFILER - storep t3, ArrayProfile::m_lastSeenStructure[t0] - end - btbz Structure::m_indexingType[t3], HasArrayStorage, .opPutByValSlow loadp JSObject::m_butterfly[t1], t0 biaeq t2, -sizeof IndexingHeader + IndexingHeader::m_vectorLength[t0], .opPutByValSlow btpz ArrayStorage::m_vector[t0, t2, 8], .opPutByValEmpty diff --git a/Source/JavaScriptCore/offlineasm/armv7.rb b/Source/JavaScriptCore/offlineasm/armv7.rb index eb9472af3..b05f0e57f 100644 --- a/Source/JavaScriptCore/offlineasm/armv7.rb +++ b/Source/JavaScriptCore/offlineasm/armv7.rb @@ -683,7 +683,7 @@ def emitArmV7Compact(opcode2, opcode3, operands) $asm.puts "#{opcode3} #{armV7FlippedOperands(operands)}" else raise unless operands.size == 2 - raise unless operands[1].is_a? RegisterID + raise unless operands[1].register? if operands[0].is_a? Immediate $asm.puts "#{opcode3} #{operands[1].armV7Operand}, #{operands[1].armV7Operand}, #{operands[0].armV7Operand}" else diff --git a/Source/JavaScriptCore/offlineasm/backends.rb b/Source/JavaScriptCore/offlineasm/backends.rb index 0633f07f8..78e545738 100644 --- a/Source/JavaScriptCore/offlineasm/backends.rb +++ b/Source/JavaScriptCore/offlineasm/backends.rb @@ -56,7 +56,8 @@ class Node $activeBackend = name send("lower" + name) rescue => e - raise "Got error #{e} at #{codeOriginString}" + e.message << "At #{codeOriginString}" + raise e end end end diff --git a/Source/JavaScriptCore/runtime/Arguments.cpp b/Source/JavaScriptCore/runtime/Arguments.cpp index 47795edb2..e5e503ee1 100644 --- a/Source/JavaScriptCore/runtime/Arguments.cpp +++ b/Source/JavaScriptCore/runtime/Arguments.cpp @@ -45,10 +45,10 @@ void Arguments::visitChildren(JSCell* cell, SlotVisitor& visitor) ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); JSObject::visitChildren(thisObject, visitor); - if (thisObject->d->registerArray) - visitor.appendValues(thisObject->d->registerArray.get(), thisObject->d->numArguments); - visitor.append(&thisObject->d->callee); - visitor.append(&thisObject->d->activation); + if (thisObject->m_registerArray) + visitor.appendValues(thisObject->m_registerArray.get(), thisObject->m_numArguments); + visitor.append(&thisObject->m_callee); + visitor.append(&thisObject->m_activation); } void Arguments::destroy(JSCell* cell) @@ -58,7 +58,7 @@ void Arguments::destroy(JSCell* cell) void Arguments::copyToArguments(ExecState* exec, CallFrame* callFrame, uint32_t length) { - if (UNLIKELY(d->overrodeLength)) { + if (UNLIKELY(m_overrodeLength)) { length = min(get(exec, exec->propertyNames().length).toUInt32(exec), length); for (unsigned i = 0; i < length; i++) callFrame->setArgument(i, get(exec, i)); @@ -66,8 +66,8 @@ void Arguments::copyToArguments(ExecState* exec, CallFrame* callFrame, uint32_t } ASSERT(length == this->length(exec)); for (size_t i = 0; i < length; ++i) { - if (!d->deletedArguments || !d->deletedArguments[i]) - callFrame->setArgument(i, argument(i).get()); + if (JSValue value = tryGetArgument(i)) + callFrame->setArgument(i, value); else callFrame->setArgument(i, get(exec, i)); } @@ -75,7 +75,7 @@ void Arguments::copyToArguments(ExecState* exec, CallFrame* callFrame, uint32_t void Arguments::fillArgList(ExecState* exec, MarkedArgumentBuffer& args) { - if (UNLIKELY(d->overrodeLength)) { + if (UNLIKELY(m_overrodeLength)) { unsigned length = get(exec, exec->propertyNames().length).toUInt32(exec); for (unsigned i = 0; i < length; i++) args.append(get(exec, i)); @@ -83,8 +83,8 @@ void Arguments::fillArgList(ExecState* exec, MarkedArgumentBuffer& args) } uint32_t length = this->length(exec); for (size_t i = 0; i < length; ++i) { - if (!d->deletedArguments || !d->deletedArguments[i]) - args.append(argument(i).get()); + if (JSValue value = tryGetArgument(i)) + args.append(value); else args.append(get(exec, i)); } @@ -93,8 +93,8 @@ void Arguments::fillArgList(ExecState* exec, MarkedArgumentBuffer& args) bool Arguments::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned i, PropertySlot& slot) { Arguments* thisObject = jsCast<Arguments*>(cell); - if (i < thisObject->d->numArguments && (!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i])) { - slot.setValue(thisObject->argument(i).get()); + if (JSValue value = thisObject->tryGetArgument(i)) { + slot.setValue(value); return true; } @@ -103,10 +103,10 @@ bool Arguments::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigne void Arguments::createStrictModeCallerIfNecessary(ExecState* exec) { - if (d->overrodeCaller) + if (m_overrodeCaller) return; - d->overrodeCaller = true; + m_overrodeCaller = true; PropertyDescriptor descriptor; descriptor.setAccessorDescriptor(globalObject()->throwTypeErrorGetterSetter(exec), DontEnum | DontDelete | Accessor); methodTable()->defineOwnProperty(this, exec, exec->propertyNames().caller, descriptor, false); @@ -114,10 +114,10 @@ void Arguments::createStrictModeCallerIfNecessary(ExecState* exec) void Arguments::createStrictModeCalleeIfNecessary(ExecState* exec) { - if (d->overrodeCallee) + if (m_overrodeCallee) return; - d->overrodeCallee = true; + m_overrodeCallee = true; PropertyDescriptor descriptor; descriptor.setAccessorDescriptor(globalObject()->throwTypeErrorGetterSetter(exec), DontEnum | DontDelete | Accessor); methodTable()->defineOwnProperty(this, exec, exec->propertyNames().callee, descriptor, false); @@ -127,26 +127,26 @@ bool Arguments::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName p { Arguments* thisObject = jsCast<Arguments*>(cell); unsigned i = propertyName.asIndex(); - if (i < thisObject->d->numArguments && (!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i])) { + if (JSValue value = thisObject->tryGetArgument(i)) { ASSERT(i < PropertyName::NotAnIndex); - slot.setValue(thisObject->argument(i).get()); + slot.setValue(value); return true; } - if (propertyName == exec->propertyNames().length && LIKELY(!thisObject->d->overrodeLength)) { - slot.setValue(jsNumber(thisObject->d->numArguments)); + if (propertyName == exec->propertyNames().length && LIKELY(!thisObject->m_overrodeLength)) { + slot.setValue(jsNumber(thisObject->m_numArguments)); return true; } - if (propertyName == exec->propertyNames().callee && LIKELY(!thisObject->d->overrodeCallee)) { - if (!thisObject->d->isStrictMode) { - slot.setValue(thisObject->d->callee.get()); + if (propertyName == exec->propertyNames().callee && LIKELY(!thisObject->m_overrodeCallee)) { + if (!thisObject->m_isStrictMode) { + slot.setValue(thisObject->m_callee.get()); return true; } thisObject->createStrictModeCalleeIfNecessary(exec); } - if (propertyName == exec->propertyNames().caller && thisObject->d->isStrictMode) + if (propertyName == exec->propertyNames().caller && thisObject->m_isStrictMode) thisObject->createStrictModeCallerIfNecessary(exec); return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot); @@ -156,26 +156,26 @@ bool Arguments::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, Prop { Arguments* thisObject = jsCast<Arguments*>(object); unsigned i = propertyName.asIndex(); - if (i < thisObject->d->numArguments && (!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i])) { + if (JSValue value = thisObject->tryGetArgument(i)) { ASSERT(i < PropertyName::NotAnIndex); - descriptor.setDescriptor(thisObject->argument(i).get(), None); + descriptor.setDescriptor(value, None); return true; } - if (propertyName == exec->propertyNames().length && LIKELY(!thisObject->d->overrodeLength)) { - descriptor.setDescriptor(jsNumber(thisObject->d->numArguments), DontEnum); + if (propertyName == exec->propertyNames().length && LIKELY(!thisObject->m_overrodeLength)) { + descriptor.setDescriptor(jsNumber(thisObject->m_numArguments), DontEnum); return true; } - if (propertyName == exec->propertyNames().callee && LIKELY(!thisObject->d->overrodeCallee)) { - if (!thisObject->d->isStrictMode) { - descriptor.setDescriptor(thisObject->d->callee.get(), DontEnum); + if (propertyName == exec->propertyNames().callee && LIKELY(!thisObject->m_overrodeCallee)) { + if (!thisObject->m_isStrictMode) { + descriptor.setDescriptor(thisObject->m_callee.get(), DontEnum); return true; } thisObject->createStrictModeCalleeIfNecessary(exec); } - if (propertyName == exec->propertyNames().caller && thisObject->d->isStrictMode) + if (propertyName == exec->propertyNames().caller && thisObject->m_isStrictMode) thisObject->createStrictModeCallerIfNecessary(exec); return JSObject::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor); @@ -184,9 +184,10 @@ bool Arguments::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, Prop void Arguments::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { Arguments* thisObject = jsCast<Arguments*>(object); - for (unsigned i = 0; i < thisObject->d->numArguments; ++i) { - if (!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i]) - propertyNames.add(Identifier(exec, String::number(i))); + for (unsigned i = 0; i < thisObject->m_numArguments; ++i) { + if (!thisObject->isArgument(i)) + continue; + propertyNames.add(Identifier(exec, String::number(i))); } if (mode == IncludeDontEnumProperties) { propertyNames.add(exec->propertyNames().callee); @@ -198,10 +199,8 @@ void Arguments::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyN void Arguments::putByIndex(JSCell* cell, ExecState* exec, unsigned i, JSValue value, bool shouldThrow) { Arguments* thisObject = jsCast<Arguments*>(cell); - if (i < static_cast<unsigned>(thisObject->d->numArguments) && (!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i])) { - thisObject->argument(i).set(exec->globalData(), thisObject, value); + if (thisObject->trySetArgument(exec->globalData(), i, value)) return; - } PutPropertySlot slot(shouldThrow); JSObject::put(thisObject, exec, Identifier(exec, String::number(i)), value, slot); @@ -211,28 +210,25 @@ void Arguments::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JS { Arguments* thisObject = jsCast<Arguments*>(cell); unsigned i = propertyName.asIndex(); - if (i < thisObject->d->numArguments && (!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i])) { - ASSERT(i < PropertyName::NotAnIndex); - thisObject->argument(i).set(exec->globalData(), thisObject, value); + if (thisObject->trySetArgument(exec->globalData(), i, value)) return; - } - if (propertyName == exec->propertyNames().length && !thisObject->d->overrodeLength) { - thisObject->d->overrodeLength = true; + if (propertyName == exec->propertyNames().length && !thisObject->m_overrodeLength) { + thisObject->m_overrodeLength = true; thisObject->putDirect(exec->globalData(), propertyName, value, DontEnum); return; } - if (propertyName == exec->propertyNames().callee && !thisObject->d->overrodeCallee) { - if (!thisObject->d->isStrictMode) { - thisObject->d->overrodeCallee = true; + if (propertyName == exec->propertyNames().callee && !thisObject->m_overrodeCallee) { + if (!thisObject->m_isStrictMode) { + thisObject->m_overrodeCallee = true; thisObject->putDirect(exec->globalData(), propertyName, value, DontEnum); return; } thisObject->createStrictModeCalleeIfNecessary(exec); } - if (propertyName == exec->propertyNames().caller && thisObject->d->isStrictMode) + if (propertyName == exec->propertyNames().caller && thisObject->m_isStrictMode) thisObject->createStrictModeCallerIfNecessary(exec); JSObject::put(thisObject, exec, propertyName, value, slot); @@ -241,20 +237,12 @@ void Arguments::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JS bool Arguments::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned i) { Arguments* thisObject = jsCast<Arguments*>(cell); - if (i < thisObject->d->numArguments) { + if (i < thisObject->m_numArguments) { if (!Base::deletePropertyByIndex(cell, exec, i)) return false; - - if (!thisObject->d->deletedArguments) { - thisObject->d->deletedArguments = adoptArrayPtr(new bool[thisObject->d->numArguments]); - memset(thisObject->d->deletedArguments.get(), 0, sizeof(bool) * thisObject->d->numArguments); - } - if (!thisObject->d->deletedArguments[i]) { - thisObject->d->deletedArguments[i] = true; + if (thisObject->tryDeleteArgument(i)) return true; - } } - return JSObject::deletePropertyByIndex(thisObject, exec, i); } @@ -265,35 +253,28 @@ bool Arguments::deleteProperty(JSCell* cell, ExecState* exec, PropertyName prope Arguments* thisObject = jsCast<Arguments*>(cell); unsigned i = propertyName.asIndex(); - if (i < thisObject->d->numArguments) { + if (i < thisObject->m_numArguments) { ASSERT(i < PropertyName::NotAnIndex); if (!Base::deleteProperty(cell, exec, propertyName)) return false; - - if (!thisObject->d->deletedArguments) { - thisObject->d->deletedArguments = adoptArrayPtr(new bool[thisObject->d->numArguments]); - memset(thisObject->d->deletedArguments.get(), 0, sizeof(bool) * thisObject->d->numArguments); - } - if (!thisObject->d->deletedArguments[i]) { - thisObject->d->deletedArguments[i] = true; + if (thisObject->tryDeleteArgument(i)) return true; - } } - if (propertyName == exec->propertyNames().length && !thisObject->d->overrodeLength) { - thisObject->d->overrodeLength = true; + if (propertyName == exec->propertyNames().length && !thisObject->m_overrodeLength) { + thisObject->m_overrodeLength = true; return true; } - if (propertyName == exec->propertyNames().callee && !thisObject->d->overrodeCallee) { - if (!thisObject->d->isStrictMode) { - thisObject->d->overrodeCallee = true; + if (propertyName == exec->propertyNames().callee && !thisObject->m_overrodeCallee) { + if (!thisObject->m_isStrictMode) { + thisObject->m_overrodeCallee = true; return true; } thisObject->createStrictModeCalleeIfNecessary(exec); } - if (propertyName == exec->propertyNames().caller && thisObject->d->isStrictMode) + if (propertyName == exec->propertyNames().caller && thisObject->m_isStrictMode) thisObject->createStrictModeCallerIfNecessary(exec); return JSObject::deleteProperty(thisObject, exec, propertyName); @@ -303,47 +284,46 @@ bool Arguments::defineOwnProperty(JSObject* object, ExecState* exec, PropertyNam { Arguments* thisObject = jsCast<Arguments*>(object); unsigned i = propertyName.asIndex(); - if (i < thisObject->d->numArguments) { + if (i < thisObject->m_numArguments) { ASSERT(i < PropertyName::NotAnIndex); // If the property is not yet present on the object, and is not yet marked as deleted, then add it now. PropertySlot slot; - if ((!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i]) && !JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot)) - object->putDirectMayBeIndex(exec, propertyName, thisObject->argument(i).get()); + if (!thisObject->isDeletedArgument(i) && !JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot)) { + JSValue value = thisObject->tryGetArgument(i); + ASSERT(value); + object->putDirectMayBeIndex(exec, propertyName, value); + } if (!Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow)) return false; - if (!thisObject->d->deletedArguments) { - thisObject->d->deletedArguments = adoptArrayPtr(new bool[thisObject->d->numArguments]); - memset(thisObject->d->deletedArguments.get(), 0, sizeof(bool) * thisObject->d->numArguments); - } // From ES 5.1, 10.6 Arguments Object // 5. If the value of isMapped is not undefined, then - if (!thisObject->d->deletedArguments[i]) { + if (thisObject->isArgument(i)) { // a. If IsAccessorDescriptor(Desc) is true, then if (descriptor.isAccessorDescriptor()) { // i. Call the [[Delete]] internal method of map passing P, and false as the arguments. - thisObject->d->deletedArguments[i] = true; + thisObject->tryDeleteArgument(i); } else { // b. Else // i. If Desc.[[Value]] is present, then // 1. Call the [[Put]] internal method of map passing P, Desc.[[Value]], and Throw as the arguments. if (descriptor.value()) - thisObject->argument(i).set(exec->globalData(), thisObject, descriptor.value()); + thisObject->trySetArgument(exec->globalData(), i, descriptor.value()); // ii. If Desc.[[Writable]] is present and its value is false, then // 1. Call the [[Delete]] internal method of map passing P and false as arguments. if (descriptor.writablePresent() && !descriptor.writable()) - thisObject->d->deletedArguments[i] = true; + thisObject->tryDeleteArgument(i); } } return true; } - if (propertyName == exec->propertyNames().length && !thisObject->d->overrodeLength) { - thisObject->putDirect(exec->globalData(), propertyName, jsNumber(thisObject->d->numArguments), DontEnum); - thisObject->d->overrodeLength = true; - } else if (propertyName == exec->propertyNames().callee && !thisObject->d->overrodeCallee) { - thisObject->putDirect(exec->globalData(), propertyName, thisObject->d->callee.get(), DontEnum); - thisObject->d->overrodeCallee = true; - } else if (propertyName == exec->propertyNames().caller && thisObject->d->isStrictMode) + if (propertyName == exec->propertyNames().length && !thisObject->m_overrodeLength) { + thisObject->putDirect(exec->globalData(), propertyName, jsNumber(thisObject->m_numArguments), DontEnum); + thisObject->m_overrodeLength = true; + } else if (propertyName == exec->propertyNames().callee && !thisObject->m_overrodeCallee) { + thisObject->putDirect(exec->globalData(), propertyName, thisObject->m_callee.get(), DontEnum); + thisObject->m_overrodeCallee = true; + } else if (propertyName == exec->propertyNames().caller && thisObject->m_isStrictMode) thisObject->createStrictModeCallerIfNecessary(exec); return Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow); @@ -354,18 +334,18 @@ void Arguments::tearOff(CallFrame* callFrame) if (isTornOff()) return; - if (!d->numArguments) + if (!m_numArguments) return; // Must be called for the same call frame from which it was created. - ASSERT(bitwise_cast<WriteBarrier<Unknown>*>(callFrame) == d->registers); + ASSERT(bitwise_cast<WriteBarrier<Unknown>*>(callFrame) == m_registers); - d->registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[d->numArguments]); - d->registers = d->registerArray.get() + CallFrame::offsetFor(d->numArguments + 1); + m_registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[m_numArguments]); + m_registers = m_registerArray.get() + CallFrame::offsetFor(m_numArguments + 1); if (!callFrame->isInlineCallFrame()) { - for (size_t i = 0; i < d->numArguments; ++i) - argument(i).set(callFrame->globalData(), this, callFrame->argument(i)); + for (size_t i = 0; i < m_numArguments; ++i) + trySetArgument(callFrame->globalData(), i, callFrame->argumentAfterCapture(i)); return; } @@ -373,16 +353,41 @@ void Arguments::tearOff(CallFrame* callFrame) callFrame->globalData(), callFrame->registers(), callFrame->inlineCallFrame()); } +void Arguments::didTearOffActivation(ExecState* exec, JSActivation* activation) +{ + ASSERT(activation); + if (isTornOff()) + return; + + if (!m_numArguments) + return; + + tearOff(exec); + + SharedSymbolTable* symbolTable = activation->symbolTable(); + const SlowArgument* slowArguments = symbolTable->slowArguments(); + if (!slowArguments) + return; + + ASSERT(symbolTable->captureMode() == SharedSymbolTable::AllOfTheThings); + m_activation.set(exec->globalData(), this, activation); + + allocateSlowArguments(); + size_t count = min<unsigned>(m_numArguments, symbolTable->parameterCount()); + for (size_t i = 0; i < count; ++i) + m_slowArguments[i] = slowArguments[i]; +} + void Arguments::tearOff(CallFrame* callFrame, InlineCallFrame* inlineCallFrame) { if (isTornOff()) return; - if (!d->numArguments) + if (!m_numArguments) return; - d->registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[d->numArguments]); - d->registers = d->registerArray.get() + CallFrame::offsetFor(d->numArguments + 1); + m_registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[m_numArguments]); + m_registers = m_registerArray.get() + CallFrame::offsetFor(m_numArguments + 1); tearOffForInlineCallFrame( callFrame->globalData(), callFrame->registers() + inlineCallFrame->stackOffset, @@ -391,7 +396,7 @@ void Arguments::tearOff(CallFrame* callFrame, InlineCallFrame* inlineCallFrame) void Arguments::tearOffForInlineCallFrame(JSGlobalData& globalData, Register* registers, InlineCallFrame* inlineCallFrame) { - for (size_t i = 0; i < d->numArguments; ++i) { + for (size_t i = 0; i < m_numArguments; ++i) { ValueRecovery& recovery = inlineCallFrame->arguments[i + 1]; // In the future we'll support displaced recoveries (indicating that the // argument was flushed to a different location), but for now we don't do @@ -427,7 +432,7 @@ void Arguments::tearOffForInlineCallFrame(JSGlobalData& globalData, Register* re ASSERT_NOT_REACHED(); break; } - argument(i).set(globalData, this, value); + trySetArgument(globalData, i, value); } } diff --git a/Source/JavaScriptCore/runtime/Arguments.h b/Source/JavaScriptCore/runtime/Arguments.h index c3d25f962..ad0e651ea 100644 --- a/Source/JavaScriptCore/runtime/Arguments.h +++ b/Source/JavaScriptCore/runtime/Arguments.h @@ -33,31 +33,9 @@ namespace JSC { - struct ArgumentsData { - WTF_MAKE_NONCOPYABLE(ArgumentsData); WTF_MAKE_FAST_ALLOCATED; - public: - ArgumentsData() { } - WriteBarrier<JSActivation> activation; - - unsigned numArguments; - - // We make these full byte booleans to make them easy to test from the JIT, - // and because even if they were single-bit booleans we still wouldn't save - // any space. - bool overrodeLength; - bool overrodeCallee; - bool overrodeCaller; - bool isStrictMode; - - WriteBarrierBase<Unknown>* registers; - OwnArrayPtr<WriteBarrier<Unknown> > registerArray; - - OwnArrayPtr<bool> deletedArguments; - - WriteBarrier<JSFunction> callee; - }; - class Arguments : public JSNonFinalObject { + friend class JIT; + friend class DFG::SpeculativeJIT; public: typedef JSNonFinalObject Base; @@ -94,30 +72,22 @@ namespace JSC { uint32_t length(ExecState* exec) const { - if (UNLIKELY(d->overrodeLength)) + if (UNLIKELY(m_overrodeLength)) return get(exec, exec->propertyNames().length).toUInt32(exec); - return d->numArguments; + return m_numArguments; } void copyToArguments(ExecState*, CallFrame*, uint32_t length); void tearOff(CallFrame*); void tearOff(CallFrame*, InlineCallFrame*); - bool isTornOff() const { return d->registerArray; } - void didTearOffActivation(JSGlobalData& globalData, JSActivation* activation) - { - if (isTornOff()) - return; - d->activation.set(globalData, this, activation); - d->registers = &activation->registerAt(0); - } + bool isTornOff() const { return m_registerArray; } + void didTearOffActivation(ExecState*, JSActivation*); static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) { return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); } - static ptrdiff_t offsetOfData() { return OBJECT_OFFSETOF(Arguments, d); } - protected: static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags; @@ -138,11 +108,34 @@ namespace JSC { void createStrictModeCallerIfNecessary(ExecState*); void createStrictModeCalleeIfNecessary(ExecState*); + bool isArgument(size_t); + bool trySetArgument(JSGlobalData&, size_t argument, JSValue); + JSValue tryGetArgument(size_t argument); + bool isDeletedArgument(size_t); + bool tryDeleteArgument(size_t); WriteBarrierBase<Unknown>& argument(size_t); + void allocateSlowArguments(); void init(CallFrame*); - OwnPtr<ArgumentsData> d; + WriteBarrier<JSActivation> m_activation; + + unsigned m_numArguments; + + // We make these full byte booleans to make them easy to test from the JIT, + // and because even if they were single-bit booleans we still wouldn't save + // any space. + bool m_overrodeLength; + bool m_overrodeCallee; + bool m_overrodeCaller; + bool m_isStrictMode; + + WriteBarrierBase<Unknown>* m_registers; + OwnArrayPtr<WriteBarrier<Unknown> > m_registerArray; + + OwnArrayPtr<SlowArgument> m_slowArguments; + + WriteBarrier<JSFunction> m_callee; }; Arguments* asArguments(JSValue); @@ -155,19 +148,76 @@ namespace JSC { inline Arguments::Arguments(CallFrame* callFrame) : JSNonFinalObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure()) - , d(adoptPtr(new ArgumentsData)) { } inline Arguments::Arguments(CallFrame* callFrame, NoParametersType) : JSNonFinalObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure()) - , d(adoptPtr(new ArgumentsData)) { } - inline WriteBarrierBase<Unknown>& Arguments::argument(size_t i) + inline void Arguments::allocateSlowArguments() + { + if (m_slowArguments) + return; + m_slowArguments = adoptArrayPtr(new SlowArgument[m_numArguments]); + } + + inline bool Arguments::tryDeleteArgument(size_t argument) { - return d->registers[CallFrame::argumentOffset(i)]; + if (!isArgument(argument)) + return false; + allocateSlowArguments(); + m_slowArguments[argument].status = SlowArgument::Deleted; + return true; + } + + inline bool Arguments::trySetArgument(JSGlobalData& globalData, size_t argument, JSValue value) + { + if (!isArgument(argument)) + return false; + this->argument(argument).set(globalData, this, value); + return true; + } + + inline JSValue Arguments::tryGetArgument(size_t argument) + { + if (!isArgument(argument)) + return JSValue(); + return this->argument(argument).get(); + } + + inline bool Arguments::isDeletedArgument(size_t argument) + { + if (argument >= m_numArguments) + return false; + if (!m_slowArguments) + return false; + if (m_slowArguments[argument].status != SlowArgument::Deleted) + return false; + return true; + } + + inline bool Arguments::isArgument(size_t argument) + { + if (argument >= m_numArguments) + return false; + if (m_slowArguments && m_slowArguments[argument].status == SlowArgument::Deleted) + return false; + return true; + } + + inline WriteBarrierBase<Unknown>& Arguments::argument(size_t argument) + { + ASSERT(isArgument(argument)); + if (!m_slowArguments || m_slowArguments[argument].status == SlowArgument::Normal) + return m_registers[CallFrame::argumentOffset(argument)]; + + ASSERT(m_slowArguments[argument].status == SlowArgument::Captured); + if (!m_activation) + return m_registers[m_slowArguments[argument].indexIfCaptured]; + + return m_activation->registerAt(m_slowArguments[argument].indexIfCaptured); } inline void Arguments::finishCreation(CallFrame* callFrame) @@ -176,17 +226,17 @@ namespace JSC { ASSERT(inherits(&s_info)); JSFunction* callee = jsCast<JSFunction*>(callFrame->callee()); - d->numArguments = callFrame->argumentCount(); - d->registers = reinterpret_cast<WriteBarrierBase<Unknown>*>(callFrame->registers()); - d->callee.set(callFrame->globalData(), this, callee); - d->overrodeLength = false; - d->overrodeCallee = false; - d->overrodeCaller = false; - d->isStrictMode = callFrame->codeBlock()->isStrictMode(); + m_numArguments = callFrame->argumentCount(); + m_registers = reinterpret_cast<WriteBarrierBase<Unknown>*>(callFrame->registers()); + m_callee.set(callFrame->globalData(), this, callee); + m_overrodeLength = false; + m_overrodeCallee = false; + m_overrodeCaller = false; + m_isStrictMode = callFrame->codeBlock()->isStrictMode(); // The bytecode generator omits op_tear_off_activation in cases of no // declared parameters, so we need to tear off immediately. - if (d->isStrictMode || !callee->jsExecutable()->parameterCount()) + if (m_isStrictMode || !callee->jsExecutable()->parameterCount()) tearOff(callFrame); } @@ -196,17 +246,17 @@ namespace JSC { ASSERT(inherits(&s_info)); JSFunction* callee = inlineCallFrame->callee.get(); - d->numArguments = inlineCallFrame->arguments.size() - 1; - d->registers = reinterpret_cast<WriteBarrierBase<Unknown>*>(callFrame->registers()) + inlineCallFrame->stackOffset; - d->callee.set(callFrame->globalData(), this, callee); - d->overrodeLength = false; - d->overrodeCallee = false; - d->overrodeCaller = false; - d->isStrictMode = jsCast<FunctionExecutable*>(inlineCallFrame->executable.get())->isStrictMode(); + m_numArguments = inlineCallFrame->arguments.size() - 1; + m_registers = reinterpret_cast<WriteBarrierBase<Unknown>*>(callFrame->registers()) + inlineCallFrame->stackOffset; + m_callee.set(callFrame->globalData(), this, callee); + m_overrodeLength = false; + m_overrodeCallee = false; + m_overrodeCaller = false; + m_isStrictMode = jsCast<FunctionExecutable*>(inlineCallFrame->executable.get())->isStrictMode(); // The bytecode generator omits op_tear_off_activation in cases of no // declared parameters, so we need to tear off immediately. - if (d->isStrictMode || !callee->jsExecutable()->parameterCount()) + if (m_isStrictMode || !callee->jsExecutable()->parameterCount()) tearOff(callFrame, inlineCallFrame); } diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp index 503aecda8..c70e40d77 100644 --- a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -132,8 +132,10 @@ ArrayPrototype::ArrayPrototype(JSGlobalObject* globalObject, Structure* structur void ArrayPrototype::finishCreation(JSGlobalObject* globalObject) { - Base::finishCreation(globalObject->globalData()); + JSGlobalData& globalData = globalObject->globalData(); + Base::finishCreation(globalData); ASSERT(inherits(&s_info)); + notifyUsedAsPrototype(globalData); } bool ArrayPrototype::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot& slot) @@ -638,7 +640,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec) CallData callData; CallType callType = getCallData(function, callData); - if (thisObj->classInfo() == &JSArray::s_info && !asArray(thisObj)->inSparseIndexingMode()) { + if (thisObj->classInfo() == &JSArray::s_info && !asArray(thisObj)->inSparseIndexingMode() && !shouldUseSlowPut(thisObj->structure()->indexingType())) { if (isNumericCompareFunction(exec, callType, callData)) asArray(thisObj)->sortNumeric(exec, function, callType, callData); else if (callType != CallTypeNone) diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp index b11220bea..2791c65d4 100644 --- a/Source/JavaScriptCore/runtime/Executable.cpp +++ b/Source/JavaScriptCore/runtime/Executable.cpp @@ -202,7 +202,7 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, JSScope* scope, JITCo m_evalCodeBlock = newCodeBlock.release(); } else { if (!lexicalGlobalObject->evalEnabled()) - return throwError(exec, createEvalError(exec, ASCIILiteral("Eval is disabled"))); + return throwError(exec, createEvalError(exec, lexicalGlobalObject->evalDisabledErrorMessage())); RefPtr<EvalNode> evalNode = parse<EvalNode>(globalData, lexicalGlobalObject, m_source, 0, Identifier(), isStrictMode() ? JSParseStrict : JSParseNormal, EvalNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception); if (!evalNode) { ASSERT(exception); diff --git a/Source/JavaScriptCore/runtime/FunctionConstructor.cpp b/Source/JavaScriptCore/runtime/FunctionConstructor.cpp index 40507dae1..570444e3c 100644 --- a/Source/JavaScriptCore/runtime/FunctionConstructor.cpp +++ b/Source/JavaScriptCore/runtime/FunctionConstructor.cpp @@ -82,7 +82,7 @@ CallType FunctionConstructor::getCallData(JSCell*, CallData& callData) JSObject* constructFunction(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, const Identifier& functionName, const String& sourceURL, const TextPosition& position) { if (!globalObject->evalEnabled()) - return throwError(exec, createEvalError(exec, ASCIILiteral("Function constructor is disabled"))); + return throwError(exec, createEvalError(exec, globalObject->evalDisabledErrorMessage())); return constructFunctionSkippingEvalEnabledCheck(exec, globalObject, args, functionName, sourceURL, position); } diff --git a/Source/JavaScriptCore/runtime/IndexingType.h b/Source/JavaScriptCore/runtime/IndexingType.h index cd8d71dfe..3b97230ea 100644 --- a/Source/JavaScriptCore/runtime/IndexingType.h +++ b/Source/JavaScriptCore/runtime/IndexingType.h @@ -33,28 +33,65 @@ typedef uint8_t IndexingType; // Flags for testing the presence of capabilities. static const IndexingType IsArray = 1; static const IndexingType HasArrayStorage = 8; +static const IndexingType HasSlowPutArrayStorage = 16; // Additional flags for tracking the history of the type. These are usually // masked off unless you ask for them directly. -static const IndexingType HadArrayStorage = 16; // Means that this object did have array storage in the past. +static const IndexingType HadArrayStorage = 32; // Means that this object did have array storage in the past. +static const IndexingType MayHaveIndexedAccessors = 64; // List of acceptable array types. -static const IndexingType NonArray = 0; -static const IndexingType NonArrayWithArrayStorage = HasArrayStorage; -static const IndexingType ArrayClass = IsArray; // I'd want to call this "Array" but this would lead to disastrous namespace pollution. -static const IndexingType ArrayWithArrayStorage = IsArray | HasArrayStorage; +static const IndexingType NonArray = 0; +static const IndexingType NonArrayWithArrayStorage = HasArrayStorage; +static const IndexingType NonArrayWithSlowPutArrayStorage = HasSlowPutArrayStorage; +static const IndexingType ArrayClass = IsArray; // I'd want to call this "Array" but this would lead to disastrous namespace pollution. +static const IndexingType ArrayWithArrayStorage = IsArray | HasArrayStorage; +static const IndexingType ArrayWithSlowPutArrayStorage = IsArray | HasSlowPutArrayStorage; -// Mask of all possible types. -static const IndexingType AllArrayTypes = 15; +#define ALL_BLANK_INDEXING_TYPES \ + NonArray: \ + case ArrayClass -// Mask of all possible types including the history. -static const IndexingType AllArrayTypesAndHistory = 31; +#define ARRAY_WITH_ARRAY_STORAGE_INDEXING_TYPES \ + ArrayWithArrayStorage: \ + case ArrayWithSlowPutArrayStorage + +#define ALL_ARRAY_STORAGE_INDEXING_TYPES \ + NonArrayWithArrayStorage: \ + case NonArrayWithSlowPutArrayStorage: \ + case ARRAY_WITH_ARRAY_STORAGE_INDEXING_TYPES + +static inline bool hasIndexedProperties(IndexingType indexingType) +{ + switch (indexingType) { + case ALL_BLANK_INDEXING_TYPES: + return false; + default: + return true; + } +} + +static inline bool hasIndexingHeader(IndexingType type) +{ + return hasIndexedProperties(type); +} -inline bool hasIndexingHeader(IndexingType type) +static inline bool hasArrayStorage(IndexingType indexingType) { - return !!(type & HasArrayStorage); + return !!(indexingType & (HasArrayStorage | HasSlowPutArrayStorage)); } +static inline bool shouldUseSlowPut(IndexingType indexingType) +{ + return !!(indexingType & HasSlowPutArrayStorage); +} + +// Mask of all possible types. +static const IndexingType AllArrayTypes = 31; + +// Mask of all possible types including the history. +static const IndexingType AllArrayTypesAndHistory = 127; + } // namespace JSC #endif // IndexingType_h diff --git a/Source/JavaScriptCore/runtime/InitializeThreading.cpp b/Source/JavaScriptCore/runtime/InitializeThreading.cpp index 6e7eddbf1..1a7239f60 100644 --- a/Source/JavaScriptCore/runtime/InitializeThreading.cpp +++ b/Source/JavaScriptCore/runtime/InitializeThreading.cpp @@ -35,6 +35,7 @@ #include "Identifier.h" #include "JSDateMath.h" #include "JSGlobalObject.h" +#include "JSLock.h" #include "LLIntData.h" #include "WriteBarrier.h" #include <wtf/dtoa.h> @@ -53,6 +54,7 @@ static void initializeThreadingOnce() { WTF::double_conversion::initialize(); WTF::initializeThreading(); + GlobalJSLock::initialize(); Options::initialize(); #if ENABLE(WRITE_BARRIER_PROFILING) WriteBarrierCounters::initialize(); diff --git a/Source/JavaScriptCore/runtime/JSActivation.h b/Source/JavaScriptCore/runtime/JSActivation.h index df59c3d94..8211e7710 100644 --- a/Source/JavaScriptCore/runtime/JSActivation.h +++ b/Source/JavaScriptCore/runtime/JSActivation.h @@ -48,7 +48,7 @@ namespace JSC { static JSActivation* create(JSGlobalData& globalData, CallFrame* callFrame, FunctionExecutable* functionExecutable) { - size_t storageSize = JSActivation::storageSize(callFrame, functionExecutable->symbolTable()); + size_t storageSize = JSActivation::storageSize(functionExecutable->symbolTable()); JSActivation* activation = new ( NotNull, allocateCell<JSActivation>( @@ -98,8 +98,8 @@ namespace JSC { NEVER_INLINE PropertySlot::GetValueFunc getArgumentsGetter(); static size_t allocationSize(size_t storageSize); - static size_t storageSize(CallFrame*, SharedSymbolTable*); - static int captureStart(CallFrame*, SharedSymbolTable*); + static size_t storageSize(SharedSymbolTable*); + static int captureStart(SharedSymbolTable*); int registerOffset(); size_t storageSize(); @@ -142,26 +142,26 @@ namespace JSC { return false; } - inline int JSActivation::captureStart(CallFrame* callFrame, SharedSymbolTable* symbolTable) + inline int JSActivation::captureStart(SharedSymbolTable* symbolTable) { if (symbolTable->captureMode() == SharedSymbolTable::AllOfTheThings) - return -CallFrame::offsetFor(std::max<size_t>(callFrame->argumentCountIncludingThis(), symbolTable->parameterCountIncludingThis())); + return -CallFrame::offsetFor(symbolTable->parameterCountIncludingThis()); return symbolTable->captureStart(); } - inline size_t JSActivation::storageSize(CallFrame* callFrame, SharedSymbolTable* symbolTable) + inline size_t JSActivation::storageSize(SharedSymbolTable* symbolTable) { - return symbolTable->captureEnd() - captureStart(callFrame, symbolTable); + return symbolTable->captureEnd() - captureStart(symbolTable); } inline int JSActivation::registerOffset() { - return -captureStart(CallFrame::create(reinterpret_cast<Register*>(m_registers)), symbolTable()); + return -captureStart(symbolTable()); } inline size_t JSActivation::storageSize() { - return storageSize(CallFrame::create(reinterpret_cast<Register*>(m_registers)), symbolTable()); + return storageSize(symbolTable()); } inline void JSActivation::tearOff(JSGlobalData& globalData) @@ -216,7 +216,7 @@ namespace JSC { inline bool JSActivation::isValid(const SymbolTableEntry& entry) { - if (entry.getIndex() < captureStart(CallFrame::create(reinterpret_cast<Register*>(m_registers)), symbolTable())) + if (entry.getIndex() < captureStart(symbolTable())) return false; if (entry.getIndex() >= symbolTable()->captureEnd()) return false; diff --git a/Source/JavaScriptCore/runtime/JSArray.cpp b/Source/JavaScriptCore/runtime/JSArray.cpp index 241049dce..ebbbd41aa 100644 --- a/Source/JavaScriptCore/runtime/JSArray.cpp +++ b/Source/JavaScriptCore/runtime/JSArray.cpp @@ -34,7 +34,6 @@ #include "IndexingHeaderInlineMethods.h" #include "PropertyNameArray.h" #include "Reject.h" -#include "SparseArrayValueMapInlineMethods.h" #include <wtf/AVLTree.h> #include <wtf/Assertions.h> #include <wtf/OwnPtr.h> @@ -405,7 +404,7 @@ JSValue JSArray::pop(ExecState* exec) case ArrayClass: return jsUndefined(); - case ArrayWithArrayStorage: { + case ARRAY_WITH_ARRAY_STORAGE_INDEXING_TYPES: { ArrayStorage* storage = m_butterfly->arrayStorage(); unsigned length = storage->length(); @@ -465,6 +464,16 @@ void JSArray::push(ExecState* exec, JSValue value) break; } + case ArrayWithSlowPutArrayStorage: { + unsigned oldLength = length(); + if (attemptToInterceptPutByIndexOnHole(exec, oldLength, value, true)) { + if (!exec->hadException() && oldLength < 0xFFFFFFFFu) + setLength(exec, oldLength + 1, true); + return; + } + // Fall through. + } + case ArrayWithArrayStorage: { ArrayStorage* storage = m_butterfly->arrayStorage(); @@ -478,8 +487,8 @@ void JSArray::push(ExecState* exec, JSValue value) return; } - // Pushing to an array of length 2^32-1 stores the property, but throws a range error. - if (UNLIKELY(storage->length() == 0xFFFFFFFFu)) { + // Pushing to an array of invalid length (2^31-1) stores the property, but throws a range error. + if (storage->length() > MAX_ARRAY_INDEX) { methodTable()->putByIndex(this, exec, storage->length(), value, true); // Per ES5.1 15.4.4.7 step 6 & 15.4.5.1 step 3.d. if (!exec->hadException()) @@ -549,7 +558,9 @@ bool JSArray::unshiftCount(ExecState* exec, unsigned count) storage = m_butterfly->arrayStorage(); storage->m_indexBias -= count; storage->setVectorLength(storage->vectorLength() + count); - } else if (!unshiftCountSlowCase(exec->globalData(), count)) { + } else if (unshiftCountSlowCase(exec->globalData(), count)) + storage = arrayStorage(); + else { throwOutOfMemoryError(exec); return true; } @@ -916,7 +927,7 @@ void JSArray::fillArgList(ExecState* exec, MarkedArgumentBuffer& args) case ArrayClass: return; - case ArrayWithArrayStorage: { + case ARRAY_WITH_ARRAY_STORAGE_INDEXING_TYPES: { ArrayStorage* storage = m_butterfly->arrayStorage(); WriteBarrier<Unknown>* vector = storage->m_vector; @@ -946,7 +957,7 @@ void JSArray::copyToArguments(ExecState* exec, CallFrame* callFrame, uint32_t le case ArrayClass: return; - case ArrayWithArrayStorage: { + case ARRAY_WITH_ARRAY_STORAGE_INDEXING_TYPES: { ArrayStorage* storage = m_butterfly->arrayStorage(); unsigned i = 0; WriteBarrier<Unknown>* vector = storage->m_vector; diff --git a/Source/JavaScriptCore/runtime/JSArray.h b/Source/JavaScriptCore/runtime/JSArray.h index d382f64a9..c46e67863 100644 --- a/Source/JavaScriptCore/runtime/JSArray.h +++ b/Source/JavaScriptCore/runtime/JSArray.h @@ -78,9 +78,9 @@ namespace JSC { void fillArgList(ExecState*, MarkedArgumentBuffer&); void copyToArguments(ExecState*, CallFrame*, uint32_t length); - static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype, IndexingType indexingType) { - return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info, ArrayWithArrayStorage); + return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info, indexingType); } protected: diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.cpp b/Source/JavaScriptCore/runtime/JSGlobalData.cpp index e409c8219..26f2b8616 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalData.cpp @@ -55,7 +55,6 @@ #include "ParserArena.h" #include "RegExpCache.h" #include "RegExpObject.h" -#include "SparseArrayValueMapInlineMethods.h" #include "StrictEvalActivation.h" #include "StrongInlines.h" #include <wtf/RetainPtr.h> diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp index 8ee8e1498..a6993aabc 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp @@ -111,6 +111,7 @@ static const int preferredScriptCheckTimeInterval = 1000; JSGlobalObject::JSGlobalObject(JSGlobalData& globalData, Structure* structure, const GlobalObjectMethodTable* globalObjectMethodTable) : Base(globalData, structure, 0) , m_masqueradesAsUndefinedWatchpoint(adoptRef(new WatchpointSet(InitializedWatching))) + , m_havingABadTimeWatchpoint(adoptRef(new WatchpointSet(InitializedWatching))) , m_weakRandom(Options::forceWeakRandomSeed() ? Options::forcedWeakRandomSeed() : static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0))) , m_evalEnabled(true) , m_globalObjectMethodTable(globalObjectMethodTable ? globalObjectMethodTable : &s_globalObjectMethodTable) @@ -230,7 +231,8 @@ void JSGlobalObject::reset(JSValue prototype) m_callbackObjectStructure.set(exec->globalData(), this, JSCallbackObject<JSNonFinalObject>::createStructure(exec->globalData(), this, m_objectPrototype.get())); m_arrayPrototype.set(exec->globalData(), this, ArrayPrototype::create(exec, this, ArrayPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get()))); - m_arrayStructure.set(exec->globalData(), this, JSArray::createStructure(exec->globalData(), this, m_arrayPrototype.get())); + m_arrayStructure.set(exec->globalData(), this, JSArray::createStructure(exec->globalData(), this, m_arrayPrototype.get(), ArrayWithArrayStorage)); + m_arrayStructureForSlowPut.set(exec->globalData(), this, JSArray::createStructure(exec->globalData(), this, m_arrayPrototype.get(), ArrayWithSlowPutArrayStorage)); m_regExpMatchesArrayStructure.set(exec->globalData(), this, RegExpMatchesArray::createStructure(exec->globalData(), this, m_arrayPrototype.get())); m_stringPrototype.set(exec->globalData(), this, StringPrototype::create(exec, this, StringPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get()))); @@ -329,6 +331,96 @@ void JSGlobalObject::reset(JSValue prototype) resetPrototype(exec->globalData(), prototype); } +// Private namespace for helpers for JSGlobalObject::haveABadTime() +namespace { + +class ObjectsWithBrokenIndexingFinder : public MarkedBlock::VoidFunctor { +public: + ObjectsWithBrokenIndexingFinder(MarkedArgumentBuffer&, JSGlobalObject*); + void operator()(JSCell*); + +private: + MarkedArgumentBuffer& m_foundObjects; + JSGlobalObject* m_globalObject; +}; + +ObjectsWithBrokenIndexingFinder::ObjectsWithBrokenIndexingFinder( + MarkedArgumentBuffer& foundObjects, JSGlobalObject* globalObject) + : m_foundObjects(foundObjects) + , m_globalObject(globalObject) +{ +} + +inline bool hasBrokenIndexing(JSObject* object) +{ + // This will change if we have more indexing types. + return !!(object->structure()->indexingType() & HasArrayStorage); +} + +void ObjectsWithBrokenIndexingFinder::operator()(JSCell* cell) +{ + if (!cell->isObject()) + return; + + JSObject* object = asObject(cell); + + // Run this filter first, since it's cheap, and ought to filter out a lot of objects. + if (!hasBrokenIndexing(object)) + return; + + // We only want to have a bad time in the affected global object, not in the entire + // VM. But we have to be careful, since there may be objects that claim to belong to + // a different global object that have prototypes from our global object. + bool foundGlobalObject = false; + for (JSObject* current = object; ;) { + if (current->unwrappedGlobalObject() == m_globalObject) { + foundGlobalObject = true; + break; + } + + JSValue prototypeValue = current->prototype(); + if (prototypeValue.isNull()) + break; + current = asObject(prototypeValue); + } + if (!foundGlobalObject) + return; + + m_foundObjects.append(object); +} + +} // end private namespace for helpers for JSGlobalObject::haveABadTime() + +void JSGlobalObject::haveABadTime(JSGlobalData& globalData) +{ + ASSERT(&globalData == &this->globalData()); + + if (isHavingABadTime()) + return; + + // Make sure that all allocations or indexed storage transitions that are inlining + // the assumption that it's safe to transition to a non-SlowPut array storage don't + // do so anymore. + m_havingABadTimeWatchpoint->notifyWrite(); + ASSERT(isHavingABadTime()); // The watchpoint is what tells us that we're having a bad time. + + // Make sure that all JSArray allocations that load the appropriate structure from + // this object now load a structure that uses SlowPut. + m_arrayStructure.set(globalData, this, m_arrayStructureForSlowPut.get()); + + // Make sure that all objects that have indexed storage switch to the slow kind of + // indexed storage. + MarkedArgumentBuffer foundObjects; // Use MarkedArgumentBuffer because switchToSlowPutArrayStorage() may GC. + ObjectsWithBrokenIndexingFinder finder(foundObjects, this); + globalData.heap.objectSpace().forEachLiveCell(finder); + while (!foundObjects.isEmpty()) { + JSObject* object = asObject(foundObjects.last()); + foundObjects.removeLast(); + ASSERT(hasBrokenIndexing(object)); + object->switchToSlowPutArrayStorage(globalData); + } +} + void JSGlobalObject::createThrowTypeError(ExecState* exec) { JSFunction* thrower = JSFunction::create(exec, this, 0, String(), globalFuncThrowTypeError); diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h index 406a65b51..ad56783cc 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObject.h +++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h @@ -126,7 +126,8 @@ namespace JSC { WriteBarrier<Structure> m_activationStructure; WriteBarrier<Structure> m_nameScopeStructure; WriteBarrier<Structure> m_argumentsStructure; - WriteBarrier<Structure> m_arrayStructure; + WriteBarrier<Structure> m_arrayStructure; // This gets set to m_arrayStructureForSlowPut as soon as we decide to have a bad time. + WriteBarrier<Structure> m_arrayStructureForSlowPut; WriteBarrier<Structure> m_booleanObjectStructure; WriteBarrier<Structure> m_callbackConstructorStructure; WriteBarrier<Structure> m_callbackFunctionStructure; @@ -149,12 +150,14 @@ namespace JSC { Debugger* m_debugger; RefPtr<WatchpointSet> m_masqueradesAsUndefinedWatchpoint; + RefPtr<WatchpointSet> m_havingABadTimeWatchpoint; OwnPtr<JSGlobalObjectRareData> m_rareData; WeakRandom m_weakRandom; bool m_evalEnabled; + String m_evalDisabledErrorMessage; bool m_experimentsEnabled; static JS_EXPORTDATA const GlobalObjectMethodTable s_globalObjectMethodTable; @@ -259,6 +262,7 @@ namespace JSC { Structure* nameScopeStructure() const { return m_nameScopeStructure.get(); } Structure* argumentsStructure() const { return m_argumentsStructure.get(); } Structure* arrayStructure() const { return m_arrayStructure.get(); } + void* addressOfArrayStructure() { return &m_arrayStructure; } Structure* booleanObjectStructure() const { return m_booleanObjectStructure.get(); } Structure* callbackConstructorStructure() const { return m_callbackConstructorStructure.get(); } Structure* callbackFunctionStructure() const { return m_callbackFunctionStructure.get(); } @@ -279,6 +283,14 @@ namespace JSC { Structure* stringObjectStructure() const { return m_stringObjectStructure.get(); } WatchpointSet* masqueradesAsUndefinedWatchpoint() { return m_masqueradesAsUndefinedWatchpoint.get(); } + WatchpointSet* havingABadTimeWatchpoint() { return m_havingABadTimeWatchpoint.get(); } + + bool isHavingABadTime() const + { + return m_havingABadTimeWatchpoint->hasBeenInvalidated(); + } + + void haveABadTime(JSGlobalData&); void setProfileGroup(unsigned value) { createRareDataIfNeeded(); m_rareData->profileGroup = value; } unsigned profileGroup() const @@ -304,8 +316,13 @@ namespace JSC { bool isDynamicScope(bool& requiresDynamicChecks) const; - void setEvalEnabled(bool enabled) { m_evalEnabled = enabled; } - bool evalEnabled() { return m_evalEnabled; } + bool evalEnabled() const { return m_evalEnabled; } + const String& evalDisabledErrorMessage() const { return m_evalDisabledErrorMessage; } + void setEvalEnabled(bool enabled, const String& errorMessage = String()) + { + m_evalEnabled = enabled; + m_evalDisabledErrorMessage = errorMessage; + } void resetPrototype(JSGlobalData&, JSValue prototype); diff --git a/Source/JavaScriptCore/runtime/JSLock.cpp b/Source/JavaScriptCore/runtime/JSLock.cpp index c57c9cdc5..9f02b69b8 100644 --- a/Source/JavaScriptCore/runtime/JSLock.cpp +++ b/Source/JavaScriptCore/runtime/JSLock.cpp @@ -33,21 +33,21 @@ namespace JSC { -// JSLock is only needed to support an obsolete execution model where JavaScriptCore -// automatically protected against concurrent access from multiple threads. -// So it's safe to disable it on non-mac platforms where we don't have native pthreads. -#if (OS(DARWIN) || USE(PTHREADS)) - -static pthread_mutex_t sharedInstanceLock = PTHREAD_MUTEX_INITIALIZER; +Mutex* GlobalJSLock::s_sharedInstanceLock = 0; GlobalJSLock::GlobalJSLock() { - pthread_mutex_lock(&sharedInstanceLock); + s_sharedInstanceLock->lock(); } GlobalJSLock::~GlobalJSLock() { - pthread_mutex_unlock(&sharedInstanceLock); + s_sharedInstanceLock->unlock(); +} + +void GlobalJSLock::initialize() +{ + s_sharedInstanceLock = new Mutex(); } JSLockHolder::JSLockHolder(ExecState* exec) @@ -216,95 +216,4 @@ JSLock::DropAllLocks::~DropAllLocks() m_globalData->apiLock().grabAllLocks(m_lockCount); } -#else // (OS(DARWIN) || USE(PTHREADS)) - -GlobalJSLock::GlobalJSLock() -{ -} - -GlobalJSLock::~GlobalJSLock() -{ -} - -JSLockHolder::JSLockHolder(JSGlobalData*) -{ -} - -JSLockHolder::JSLockHolder(JSGlobalData&) -{ -} - -JSLockHolder::JSLockHolder(ExecState*) -{ -} - -JSLockHolder::~JSLockHolder() -{ -} - -JSLock::JSLock() -{ -} - -JSLock::~JSLock() -{ -} - -bool JSLock::currentThreadIsHoldingLock() -{ - return true; -} - -void JSLock::lock() -{ -} - -void JSLock::unlock() -{ -} - -void JSLock::lock(ExecState*) -{ -} - -void JSLock::unlock(ExecState*) -{ -} - -void JSLock::lock(JSGlobalData&) -{ -} - -void JSLock::unlock(JSGlobalData&) -{ -} - -unsigned JSLock::dropAllLocks() -{ - return 0; -} - -unsigned JSLock::dropAllLocksUnconditionally() -{ - return 0; -} - -void JSLock::grabAllLocks(unsigned) -{ -} - -JSLock::DropAllLocks::DropAllLocks(ExecState*) -{ -} - -JSLock::DropAllLocks::DropAllLocks(JSGlobalData*) -{ -} - -JSLock::DropAllLocks::~DropAllLocks() -{ -} - -#endif // (OS(DARWIN) || USE(PTHREADS)) - } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSLock.h b/Source/JavaScriptCore/runtime/JSLock.h index 94108d013..4c42dc0ae 100644 --- a/Source/JavaScriptCore/runtime/JSLock.h +++ b/Source/JavaScriptCore/runtime/JSLock.h @@ -58,6 +58,10 @@ namespace JSC { public: JS_EXPORT_PRIVATE GlobalJSLock(); JS_EXPORT_PRIVATE ~GlobalJSLock(); + + static void initialize(); + private: + static Mutex* s_sharedInstanceLock; }; class JSLockHolder { @@ -91,12 +95,6 @@ namespace JSC { unsigned dropAllLocksUnconditionally(); void grabAllLocks(unsigned lockCount); - SpinLock m_spinLock; - Mutex m_lock; - ThreadIdentifier m_ownerThread; - intptr_t m_lockCount; - unsigned m_lockDropDepth; - class DropAllLocks { WTF_MAKE_NONCOPYABLE(DropAllLocks); public: @@ -108,6 +106,13 @@ namespace JSC { intptr_t m_lockCount; RefPtr<JSGlobalData> m_globalData; }; + + private: + SpinLock m_spinLock; + Mutex m_lock; + ThreadIdentifier m_ownerThread; + intptr_t m_lockCount; + unsigned m_lockDropDepth; }; } // namespace diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp index 6eac0d1cb..229d1aea6 100644 --- a/Source/JavaScriptCore/runtime/JSObject.cpp +++ b/Source/JavaScriptCore/runtime/JSObject.cpp @@ -42,7 +42,6 @@ #include "PropertyNameArray.h" #include "Reject.h" #include "SlotVisitorInlineMethods.h" -#include "SparseArrayValueMapInlineMethods.h" #include <math.h> #include <wtf/Assertions.h> @@ -50,7 +49,8 @@ namespace JSC { // We keep track of the size of the last array after it was grown. We use this // as a simple heuristic for as the value to grow the next array from size 0. -// This value is capped by the constant FIRST_VECTOR_GROW defined above. +// This value is capped by the constant FIRST_VECTOR_GROW defined in +// ArrayConventions.h. static unsigned lastArraySize = 0; JSCell* getCallableObjectSlow(JSCell* cell) @@ -133,8 +133,7 @@ ALWAYS_INLINE void JSObject::visitButterfly(SlotVisitor& visitor, Butterfly* but // Mark and copy the array if appropriate. switch (structure->indexingType()) { - case ArrayWithArrayStorage: - case NonArrayWithArrayStorage: { + case ALL_ARRAY_STORAGE_INDEXING_TYPES: { newButterfly->arrayStorage()->copyHeaderFromDuringGC(*butterfly->arrayStorage()); WriteBarrier<Unknown>* currentTarget = newButterfly->arrayStorage()->m_vector; WriteBarrier<Unknown>* currentSource = butterfly->arrayStorage()->m_vector; @@ -160,8 +159,7 @@ ALWAYS_INLINE void JSObject::visitButterfly(SlotVisitor& visitor, Butterfly* but // Mark the array if appropriate. switch (structure->indexingType()) { - case ArrayWithArrayStorage: - case NonArrayWithArrayStorage: + case ALL_ARRAY_STORAGE_INDEXING_TYPES: visitor.appendValues(butterfly->arrayStorage()->m_vector, butterfly->arrayStorage()->vectorLength()); if (butterfly->arrayStorage()->m_sparseMap) visitor.append(&butterfly->arrayStorage()->m_sparseMap); @@ -234,12 +232,10 @@ bool JSObject::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned return thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, Identifier::from(exec, i), slot); switch (thisObject->structure()->indexingType()) { - case NonArray: - case ArrayClass: + case ALL_BLANK_INDEXING_TYPES: break; - case NonArrayWithArrayStorage: - case ArrayWithArrayStorage: { + case ALL_ARRAY_STORAGE_INDEXING_TYPES: { ArrayStorage* storage = thisObject->m_butterfly->arrayStorage(); if (i >= storage->length()) return false; @@ -301,7 +297,7 @@ void JSObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSV unsigned attributes; JSCell* specificValue; PropertyOffset offset = obj->structure()->get(globalData, propertyName, attributes, specificValue); - if (offset != invalidOffset) { + if (isValidOffset(offset)) { if (attributes & ReadOnly) { if (slot.isStrictMode()) throwError(exec, createTypeError(exec, ASCIILiteral(StrictModeReadonlyPropertyWriteError))); @@ -347,15 +343,14 @@ void JSObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSObject* thisObject = jsCast<JSObject*>(cell); thisObject->checkIndexingConsistency(); - if (UNLIKELY(propertyName > MAX_ARRAY_INDEX)) { + if (propertyName > MAX_ARRAY_INDEX) { PutPropertySlot slot(shouldThrow); thisObject->methodTable()->put(thisObject, exec, Identifier::from(exec, propertyName), value, slot); return; } switch (thisObject->structure()->indexingType()) { - case NonArray: - case ArrayClass: + case ALL_BLANK_INDEXING_TYPES: break; case NonArrayWithArrayStorage: @@ -381,6 +376,34 @@ void JSObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, return; } + case NonArrayWithSlowPutArrayStorage: + case ArrayWithSlowPutArrayStorage: { + ArrayStorage* storage = thisObject->m_butterfly->arrayStorage(); + + if (propertyName >= storage->vectorLength()) + break; + + WriteBarrier<Unknown>& valueSlot = storage->m_vector[propertyName]; + unsigned length = storage->length(); + + // Update length & m_numValuesInVector as necessary. + if (propertyName >= length) { + if (thisObject->attemptToInterceptPutByIndexOnHole(exec, propertyName, value, shouldThrow)) + return; + length = propertyName + 1; + storage->setLength(length); + ++storage->m_numValuesInVector; + } else if (!valueSlot) { + if (thisObject->attemptToInterceptPutByIndexOnHole(exec, propertyName, value, shouldThrow)) + return; + ++storage->m_numValuesInVector; + } + + valueSlot.set(exec->globalData(), thisObject, value); + thisObject->checkIndexingConsistency(); + return; + } + default: ASSERT_NOT_REACHED(); } @@ -425,8 +448,7 @@ ArrayStorage* JSObject::enterDictionaryIndexingModeWhenArrayStorageAlreadyExists void JSObject::enterDictionaryIndexingMode(JSGlobalData& globalData) { switch (structure()->indexingType()) { - case ArrayWithArrayStorage: - case NonArrayWithArrayStorage: + case ALL_ARRAY_STORAGE_INDEXING_TYPES: enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, m_butterfly->arrayStorage()); break; @@ -435,10 +457,23 @@ void JSObject::enterDictionaryIndexingMode(JSGlobalData& globalData) } } +void JSObject::notifyPresenceOfIndexedAccessors(JSGlobalData& globalData) +{ + if (mayInterceptIndexedAccesses()) + return; + + setStructure(globalData, Structure::nonPropertyTransition(globalData, structure(), AddIndexedAccessors)); + + if (!mayBeUsedAsPrototype(globalData)) + return; + + globalObject()->haveABadTime(globalData); +} + ArrayStorage* JSObject::createArrayStorage(JSGlobalData& globalData, unsigned length, unsigned vectorLength) { IndexingType oldType = structure()->indexingType(); - ASSERT_UNUSED(oldType, oldType == NonArray || oldType == ArrayClass); + ASSERT_UNUSED(oldType, !hasIndexedProperties(oldType)); Butterfly* newButterfly = m_butterfly->growArrayRight( globalData, structure(), structure()->outOfLineCapacity(), false, 0, ArrayStorage::sizeFor(vectorLength)); @@ -454,7 +489,7 @@ ArrayStorage* JSObject::createArrayStorage(JSGlobalData& globalData, unsigned le result->m_initializationIndex = 0; result->m_inCompactInitialization = 0; #endif - Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), AllocateArrayStorage); + Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), structure()->suggestedIndexingTransition()); setButterfly(globalData, newButterfly, newStructure); return result; } @@ -467,12 +502,10 @@ ArrayStorage* JSObject::createInitialArrayStorage(JSGlobalData& globalData) ArrayStorage* JSObject::ensureArrayStorageExistsAndEnterDictionaryIndexingMode(JSGlobalData& globalData) { switch (structure()->indexingType()) { - case ArrayWithArrayStorage: - case NonArrayWithArrayStorage: + case ALL_ARRAY_STORAGE_INDEXING_TYPES: return enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, m_butterfly->arrayStorage()); - case ArrayClass: - case NonArray: { + case ALL_BLANK_INDEXING_TYPES: { createArrayStorage(globalData, 0, 0); SparseArrayValueMap* map = allocateSparseIndexMap(globalData); map->setSparseMode(); @@ -485,6 +518,22 @@ ArrayStorage* JSObject::ensureArrayStorageExistsAndEnterDictionaryIndexingMode(J } } +void JSObject::switchToSlowPutArrayStorage(JSGlobalData& globalData) +{ + switch (structure()->indexingType()) { + case NonArrayWithArrayStorage: + case ArrayWithArrayStorage: { + Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), SwitchToSlowPutArrayStorage); + setStructure(globalData, newStructure); + break; + } + + default: + ASSERT_NOT_REACHED(); + break; + } +} + void JSObject::putDirectVirtual(JSObject* object, ExecState* exec, PropertyName propertyName, JSValue value, unsigned attributes) { ASSERT(!value.isGetterSetter() && !(attributes & Accessor)); @@ -492,6 +541,33 @@ void JSObject::putDirectVirtual(JSObject* object, ExecState* exec, PropertyName object->putDirectInternal<PutModeDefineOwnProperty>(exec->globalData(), propertyName, value, attributes, slot, getCallableObject(value)); } +void JSObject::setPrototype(JSGlobalData& globalData, JSValue prototype) +{ + ASSERT(prototype); + if (prototype.isObject()) + asObject(prototype)->notifyUsedAsPrototype(globalData); + + Structure* newStructure = Structure::changePrototypeTransition(globalData, structure(), prototype); + setStructure(globalData, newStructure); + + if (!newStructure->anyObjectInChainMayInterceptIndexedAccesses()) + return; + + if (mayBeUsedAsPrototype(globalData)) { + newStructure->globalObject()->haveABadTime(globalData); + return; + } + + if (!hasIndexingHeader(structure()->indexingType())) + return; + + if (shouldUseSlowPut(structure()->indexingType())) + return; + + newStructure = Structure::nonPropertyTransition(globalData, newStructure, SwitchToSlowPutArrayStorage); + setStructure(globalData, newStructure); +} + bool JSObject::setPrototypeWithCycleCheck(JSGlobalData& globalData, JSValue prototype) { JSValue checkFor = this; @@ -508,9 +584,32 @@ bool JSObject::setPrototypeWithCycleCheck(JSGlobalData& globalData, JSValue prot return true; } +void JSObject::resetInheritorID(JSGlobalData& globalData) +{ + PropertyOffset offset = structure()->get(globalData, globalData.m_inheritorIDKey); + if (!isValidOffset(offset)) + return; + + putDirectOffset(globalData, offset, jsUndefined()); +} + +Structure* JSObject::inheritorID(JSGlobalData& globalData) +{ + if (WriteBarrierBase<Unknown>* location = getDirectLocation(globalData, globalData.m_inheritorIDKey)) { + JSValue value = location->get(); + if (value.isCell()) { + Structure* inheritorID = jsCast<Structure*>(value); + ASSERT(inheritorID->isEmpty()); + return inheritorID; + } + ASSERT(value.isUndefined()); + } + return createInheritorID(globalData); +} + bool JSObject::allowsAccessFrom(ExecState* exec) { - JSGlobalObject* globalObject = isGlobalThis() ? jsCast<JSGlobalThis*>(this)->unwrappedObject() : this->globalObject(); + JSGlobalObject* globalObject = unwrappedGlobalObject(); return globalObject->globalObjectMethodTable()->allowsAccessFrom(globalObject, exec); } @@ -597,12 +696,10 @@ bool JSObject::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned i) return thisObject->methodTable()->deleteProperty(thisObject, exec, Identifier::from(exec, i)); switch (thisObject->structure()->indexingType()) { - case ArrayClass: - case NonArray: + case ALL_BLANK_INDEXING_TYPES: return true; - case ArrayWithArrayStorage: - case NonArrayWithArrayStorage: { + case ALL_ARRAY_STORAGE_INDEXING_TYPES: { ArrayStorage* storage = thisObject->m_butterfly->arrayStorage(); if (i < storage->vectorLength()) { @@ -762,12 +859,10 @@ void JSObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNa // is incredibly inefficient for large arrays. We need a different approach, // which almost certainly means a different structure for PropertyNameArray. switch (object->structure()->indexingType()) { - case NonArray: - case ArrayClass: + case ALL_BLANK_INDEXING_TYPES: break; - case NonArrayWithArrayStorage: - case ArrayWithArrayStorage: { + case ALL_ARRAY_STORAGE_INDEXING_TYPES: { ArrayStorage* storage = object->m_butterfly->arrayStorage(); unsigned usedVectorLength = std::min(storage->length(), storage->vectorLength()); @@ -857,6 +952,13 @@ void JSObject::preventExtensions(JSGlobalData& globalData) setStructure(globalData, Structure::preventExtensionsTransition(globalData, structure())); } +JSGlobalObject* JSObject::unwrappedGlobalObject() +{ + if (isGlobalThis()) + return jsCast<JSGlobalThis*>(this)->unwrappedObject(); + return structure()->globalObject(); +} + // This presently will flatten to an uncachable dictionary; this is suitable // for use in delete, we may want to do something different elsewhere. void JSObject::reifyStaticFunctionsForDelete(ExecState* exec) @@ -920,18 +1022,35 @@ NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, PropertyO slot.setUndefined(); } -Structure* JSObject::createInheritorID(JSGlobalData& globalData) +void JSObject::notifyUsedAsPrototype(JSGlobalData& globalData) { - ASSERT(!getDirectLocation(globalData, globalData.m_inheritorIDKey)); - - JSGlobalObject* globalObject; - if (isGlobalThis()) - globalObject = static_cast<JSGlobalThis*>(this)->unwrappedObject(); - else - globalObject = structure()->globalObject(); - ASSERT(globalObject); + PropertyOffset offset = structure()->get(globalData, globalData.m_inheritorIDKey); + if (isValidOffset(offset)) + return; + + PutPropertySlot slot; + putDirectInternal<PutModeDefineOwnProperty>(globalData, globalData.m_inheritorIDKey, jsUndefined(), DontEnum, slot, 0); + + // Note that this method makes the somewhat odd decision to not check if this + // object currently has indexed accessors. We could do that check here, and if + // indexed accessors were found, we could tell the global object to have a bad + // time. But we avoid this, to allow the following to be always fast: + // + // 1) Create an object. + // 2) Give it a setter or read-only property that happens to have a numeric name. + // 3) Allocate objects that use this object as a prototype. + // + // This avoids anyone having a bad time. Even if the instance objects end up + // having indexed storage, the creation of indexed storage leads to a prototype + // chain walk that detects the presence of indexed setters and then does the + // right thing. As a result, having a bad time only happens if you add an + // indexed setter (or getter, or read-only field) to an object that is already + // used as a prototype. +} - Structure* inheritorID = createEmptyObjectStructure(globalData, globalObject, this); +Structure* JSObject::createInheritorID(JSGlobalData& globalData) +{ + Structure* inheritorID = createEmptyObjectStructure(globalData, unwrappedGlobalObject(), this); ASSERT(inheritorID->isEmpty()); PutPropertySlot slot; @@ -980,7 +1099,10 @@ void JSObject::putIndexedDescriptor(ExecState* exec, SparseArrayEntry* entryInMa // Defined in ES5.1 8.12.9 bool JSObject::defineOwnIndexedProperty(ExecState* exec, unsigned index, PropertyDescriptor& descriptor, bool throwException) { - ASSERT(index != 0xFFFFFFFF); + ASSERT(index <= MAX_ARRAY_INDEX); + + if (descriptor.attributes() & (ReadOnly | Accessor)) + notifyPresenceOfIndexedAccessors(exec->globalData()); if (!inSparseIndexingMode()) { // Fast case: we're putting a regular property to a regular array @@ -1109,6 +1231,40 @@ void JSObject::deallocateSparseIndexMap() arrayStorage->m_sparseMap.clear(); } +bool JSObject::attemptToInterceptPutByIndexOnHoleForPrototype(ExecState* exec, JSValue thisValue, unsigned i, JSValue value, bool shouldThrow) +{ + for (JSObject* current = this; ;) { + // This has the same behavior with respect to prototypes as JSObject::put(). It only + // allows a prototype to intercept a put if (a) the prototype declares the property + // we're after rather than intercepting it via an override of JSObject::put(), and + // (b) that property is declared as ReadOnly or Accessor. + + ArrayStorage* storage = current->arrayStorageOrNull(); + if (storage && storage->m_sparseMap) { + SparseArrayValueMap::iterator iter = storage->m_sparseMap->find(i); + if (iter != storage->m_sparseMap->notFound() && (iter->second.attributes & (Accessor | ReadOnly))) { + iter->second.put(exec, thisValue, storage->m_sparseMap.get(), value, shouldThrow); + return true; + } + } + + JSValue prototypeValue = current->prototype(); + if (prototypeValue.isNull()) + return false; + + current = asObject(prototypeValue); + } +} + +bool JSObject::attemptToInterceptPutByIndexOnHole(ExecState* exec, unsigned i, JSValue value, bool shouldThrow) +{ + JSValue prototypeValue = prototype(); + if (prototypeValue.isNull()) + return false; + + return asObject(prototypeValue)->attemptToInterceptPutByIndexOnHoleForPrototype(exec, this, i, value, shouldThrow); +} + void JSObject::putByIndexBeyondVectorLengthWithArrayStorage(ExecState* exec, unsigned i, JSValue value, bool shouldThrow, ArrayStorage* storage) { JSGlobalData& globalData = exec->globalData(); @@ -1189,8 +1345,7 @@ void JSObject::putByIndexBeyondVectorLength(ExecState* exec, unsigned i, JSValue ASSERT(i <= MAX_ARRAY_INDEX); switch (structure()->indexingType()) { - case NonArray: - case ArrayClass: { + case ALL_BLANK_INDEXING_TYPES: { if (indexingShouldBeSparse()) { putByIndexBeyondVectorLengthWithArrayStorage(exec, i, value, shouldThrow, ensureArrayStorageExistsAndEnterDictionaryIndexingMode(globalData)); break; @@ -1205,6 +1360,12 @@ void JSObject::putByIndexBeyondVectorLength(ExecState* exec, unsigned i, JSValue storage->m_numValuesInVector = 1; break; } + + case NonArrayWithSlowPutArrayStorage: + case ArrayWithSlowPutArrayStorage: + if (attemptToInterceptPutByIndexOnHole(exec, i, value, shouldThrow)) + return; + // Otherwise, fall though. case NonArrayWithArrayStorage: case ArrayWithArrayStorage: @@ -1297,9 +1458,11 @@ bool JSObject::putDirectIndexBeyondVectorLength(ExecState* exec, unsigned i, JSV // i should be a valid array index that is outside of the current vector. ASSERT(i <= MAX_ARRAY_INDEX); + if (attributes & (ReadOnly | Accessor)) + notifyPresenceOfIndexedAccessors(globalData); + switch (structure()->indexingType()) { - case NonArray: - case ArrayClass: { + case ALL_BLANK_INDEXING_TYPES: { if (indexingShouldBeSparse() || attributes) return putDirectIndexBeyondVectorLengthWithArrayStorage(exec, i, value, attributes, mode, ensureArrayStorageExistsAndEnterDictionaryIndexingMode(globalData)); if (!isDenseEnoughForVector(i, 0) || i >= MAX_STORAGE_VECTOR_LENGTH) @@ -1311,8 +1474,7 @@ bool JSObject::putDirectIndexBeyondVectorLength(ExecState* exec, unsigned i, JSV return true; } - case NonArrayWithArrayStorage: - case ArrayWithArrayStorage: + case ALL_ARRAY_STORAGE_INDEXING_TYPES: return putDirectIndexBeyondVectorLengthWithArrayStorage(exec, i, value, attributes, mode, arrayStorage()); default: @@ -1354,13 +1516,11 @@ ALWAYS_INLINE unsigned JSObject::getNewVectorLength(unsigned desiredLength) unsigned length; switch (structure()->indexingType()) { - case NonArray: - case ArrayClass: + case ALL_BLANK_INDEXING_TYPES: vectorLength = 0; length = 0; break; - case NonArrayWithArrayStorage: - case ArrayWithArrayStorage: + case ALL_ARRAY_STORAGE_INDEXING_TYPES: vectorLength = m_butterfly->arrayStorage()->vectorLength(); length = m_butterfly->arrayStorage()->length(); break; @@ -1478,12 +1638,10 @@ bool JSObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, Prope return false; switch (object->structure()->indexingType()) { - case NonArray: - case ArrayClass: + case ALL_BLANK_INDEXING_TYPES: return false; - case NonArrayWithArrayStorage: - case ArrayWithArrayStorage: { + case ALL_ARRAY_STORAGE_INDEXING_TYPES: { ArrayStorage* storage = object->m_butterfly->arrayStorage(); if (i >= storage->length()) return false; diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h index 8df521b75..8b52915b6 100644 --- a/Source/JavaScriptCore/runtime/JSObject.h +++ b/Source/JavaScriptCore/runtime/JSObject.h @@ -118,7 +118,18 @@ namespace JSC { bool setPrototypeWithCycleCheck(JSGlobalData&, JSValue prototype); Structure* inheritorID(JSGlobalData&); - + void notifyUsedAsPrototype(JSGlobalData&); + + bool mayBeUsedAsPrototype(JSGlobalData& globalData) + { + return isValidOffset(structure()->get(globalData, globalData.m_inheritorIDKey)); + } + + bool mayInterceptIndexedAccesses() + { + return structure()->mayInterceptIndexedAccesses(); + } + JSValue get(ExecState*, PropertyName) const; JSValue get(ExecState*, unsigned propertyName) const; @@ -135,11 +146,9 @@ namespace JSC { unsigned getArrayLength() const { switch (structure()->indexingType()) { - case NonArray: - case ArrayClass: + case ALL_BLANK_INDEXING_TYPES: return 0; - case NonArrayWithArrayStorage: - case ArrayWithArrayStorage: + case ALL_ARRAY_STORAGE_INDEXING_TYPES: return m_butterfly->arrayStorage()->length(); default: ASSERT_NOT_REACHED(); @@ -150,11 +159,9 @@ namespace JSC { unsigned getVectorLength() { switch (structure()->indexingType()) { - case NonArray: - case ArrayClass: + case ALL_BLANK_INDEXING_TYPES: return 0; - case NonArrayWithArrayStorage: - case ArrayWithArrayStorage: + case ALL_ARRAY_STORAGE_INDEXING_TYPES: return m_butterfly->arrayStorage()->vectorLength(); default: ASSERT_NOT_REACHED(); @@ -189,11 +196,9 @@ namespace JSC { bool canGetIndexQuickly(unsigned i) { switch (structure()->indexingType()) { - case NonArray: - case ArrayClass: + case ALL_BLANK_INDEXING_TYPES: return false; - case NonArrayWithArrayStorage: - case ArrayWithArrayStorage: + case ALL_ARRAY_STORAGE_INDEXING_TYPES: return i < m_butterfly->arrayStorage()->vectorLength() && m_butterfly->arrayStorage()->m_vector[i]; default: ASSERT_NOT_REACHED(); @@ -204,8 +209,7 @@ namespace JSC { JSValue getIndexQuickly(unsigned i) { switch (structure()->indexingType()) { - case NonArrayWithArrayStorage: - case ArrayWithArrayStorage: + case ALL_ARRAY_STORAGE_INDEXING_TYPES: return m_butterfly->arrayStorage()->m_vector[i].get(); default: ASSERT_NOT_REACHED(); @@ -216,12 +220,15 @@ namespace JSC { bool canSetIndexQuickly(unsigned i) { switch (structure()->indexingType()) { - case NonArray: - case ArrayClass: + case ALL_BLANK_INDEXING_TYPES: return false; case NonArrayWithArrayStorage: case ArrayWithArrayStorage: return i < m_butterfly->arrayStorage()->vectorLength(); + case NonArrayWithSlowPutArrayStorage: + case ArrayWithSlowPutArrayStorage: + return i < m_butterfly->arrayStorage()->vectorLength() + && !!m_butterfly->arrayStorage()->m_vector[i]; default: ASSERT_NOT_REACHED(); return false; @@ -231,8 +238,7 @@ namespace JSC { void setIndexQuickly(JSGlobalData& globalData, unsigned i, JSValue v) { switch (structure()->indexingType()) { - case NonArrayWithArrayStorage: - case ArrayWithArrayStorage: { + case ALL_ARRAY_STORAGE_INDEXING_TYPES: { WriteBarrier<Unknown>& x = m_butterfly->arrayStorage()->m_vector[i]; if (!x) { ArrayStorage* storage = m_butterfly->arrayStorage(); @@ -251,8 +257,7 @@ namespace JSC { void initializeIndex(JSGlobalData& globalData, unsigned i, JSValue v) { switch (structure()->indexingType()) { - case NonArrayWithArrayStorage: - case ArrayWithArrayStorage: { + case ALL_ARRAY_STORAGE_INDEXING_TYPES: { ArrayStorage* storage = m_butterfly->arrayStorage(); #if CHECK_ARRAY_CONSISTENCY ASSERT(storage->m_inCompactInitialization); @@ -276,8 +281,7 @@ namespace JSC { void completeInitialization(unsigned newLength) { switch (structure()->indexingType()) { - case NonArrayWithArrayStorage: - case ArrayWithArrayStorage: { + case ALL_ARRAY_STORAGE_INDEXING_TYPES: { ArrayStorage* storage = m_butterfly->arrayStorage(); // Check that we have initialized as meny properties as we think we have. UNUSED_PARAM(storage); @@ -298,11 +302,9 @@ namespace JSC { bool inSparseIndexingMode() { switch (structure()->indexingType()) { - case NonArray: - case ArrayClass: + case ALL_BLANK_INDEXING_TYPES: return false; - case NonArrayWithArrayStorage: - case ArrayWithArrayStorage: + case ALL_ARRAY_STORAGE_INDEXING_TYPES: return m_butterfly->arrayStorage()->inSparseMode(); default: ASSERT_NOT_REACHED(); @@ -487,6 +489,22 @@ namespace JSC { return structure()->globalObject(); } + // Does everything possible to return the global object. If it encounters an object + // that does not have a global object, it returns 0 instead (for example + // JSNotAnObject). + JSGlobalObject* unwrappedGlobalObject(); + + void switchToSlowPutArrayStorage(JSGlobalData&); + + // The receiver is the prototype in this case. The following: + // + // asObject(foo->structure()->storedPrototype())->attemptToInterceptPutByIndexOnHoleForPrototype(...) + // + // is equivalent to: + // + // foo->attemptToInterceptPutByIndexOnHole(...); + bool attemptToInterceptPutByIndexOnHoleForPrototype(ExecState*, JSValue thisValue, unsigned propertyName, JSValue, bool shouldThrow); + static size_t offsetOfInlineStorage(); static ptrdiff_t butterflyOffset() @@ -522,10 +540,7 @@ namespace JSC { // To create derived types you likely want JSNonFinalObject, below. JSObject(JSGlobalData&, Structure*, Butterfly* = 0); - void resetInheritorID(JSGlobalData& globalData) - { - removeDirect(globalData, globalData.m_inheritorIDKey); - } + void resetInheritorID(JSGlobalData&); void visitButterfly(SlotVisitor&, Butterfly*, size_t storageSize); @@ -533,7 +548,7 @@ namespace JSC { // storage. This will assert otherwise. ArrayStorage* arrayStorage() { - ASSERT(structure()->indexingType() | HasArrayStorage); + ASSERT(hasArrayStorage(structure()->indexingType())); return m_butterfly->arrayStorage(); } @@ -542,8 +557,7 @@ namespace JSC { ArrayStorage* arrayStorageOrNull() { switch (structure()->indexingType()) { - case ArrayWithArrayStorage: - case NonArrayWithArrayStorage: + case ALL_ARRAY_STORAGE_INDEXING_TYPES: return m_butterfly->arrayStorage(); default: @@ -558,12 +572,10 @@ namespace JSC { ArrayStorage* ensureArrayStorage(JSGlobalData& globalData) { switch (structure()->indexingType()) { - case ArrayWithArrayStorage: - case NonArrayWithArrayStorage: + case ALL_ARRAY_STORAGE_INDEXING_TYPES: return m_butterfly->arrayStorage(); - case NonArray: - case ArrayClass: + case ALL_BLANK_INDEXING_TYPES: return createInitialArrayStorage(globalData); default: @@ -592,6 +604,10 @@ namespace JSC { void deallocateSparseIndexMap(); bool defineOwnIndexedProperty(ExecState*, unsigned, PropertyDescriptor&, bool throwException); SparseArrayValueMap* allocateSparseIndexMap(JSGlobalData&); + + void notifyPresenceOfIndexedAccessors(JSGlobalData&); + + bool attemptToInterceptPutByIndexOnHole(ExecState*, unsigned index, JSValue, bool shouldThrow); private: friend class LLIntOffsetsExtractor; @@ -824,22 +840,6 @@ inline JSValue JSObject::prototype() const return structure()->storedPrototype(); } -inline void JSObject::setPrototype(JSGlobalData& globalData, JSValue prototype) -{ - ASSERT(prototype); - setStructure(globalData, Structure::changePrototypeTransition(globalData, structure(), prototype)); -} - -inline Structure* JSObject::inheritorID(JSGlobalData& globalData) -{ - if (WriteBarrierBase<Unknown>* location = getDirectLocation(globalData, globalData.m_inheritorIDKey)) { - Structure* inheritorID = jsCast<Structure*>(location->get()); - ASSERT(inheritorID->isEmpty()); - return inheritorID; - } - return createInheritorID(globalData); -} - inline bool JSCell::inherits(const ClassInfo* info) const { return classInfo()->isSubClassOf(info); @@ -1190,8 +1190,7 @@ inline void JSValue::put(ExecState* exec, PropertyName propertyName, JSValue val inline void JSValue::putByIndex(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow) { if (UNLIKELY(!isCell())) { - PutPropertySlot slot(shouldThrow); - putToPrimitive(exec, Identifier::from(exec, propertyName), value, slot); + putToPrimitiveByIndex(exec, propertyName, value, shouldThrow); return; } asCell()->methodTable()->putByIndex(asCell(), exec, propertyName, value, shouldThrow); diff --git a/Source/JavaScriptCore/runtime/JSValue.cpp b/Source/JavaScriptCore/runtime/JSValue.cpp index caff9973b..ac00fad3d 100644 --- a/Source/JavaScriptCore/runtime/JSValue.cpp +++ b/Source/JavaScriptCore/runtime/JSValue.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2007, 2008, 2012 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -113,6 +113,12 @@ void JSValue::putToPrimitive(ExecState* exec, PropertyName propertyName, JSValue { JSGlobalData& globalData = exec->globalData(); + unsigned index = propertyName.asIndex(); + if (index != PropertyName::NotAnIndex) { + putToPrimitiveByIndex(exec, index, value, slot.isStrictMode()); + return; + } + // Check if there are any setters or getters in the prototype chain JSObject* obj = synthesizePrototype(exec); JSValue prototype; @@ -172,6 +178,21 @@ void JSValue::putToPrimitive(ExecState* exec, PropertyName propertyName, JSValue return; } +void JSValue::putToPrimitiveByIndex(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow) +{ + if (propertyName > MAX_ARRAY_INDEX) { + PutPropertySlot slot(shouldThrow); + putToPrimitive(exec, Identifier::from(exec, propertyName), value, slot); + return; + } + + if (synthesizePrototype(exec)->attemptToInterceptPutByIndexOnHoleForPrototype(exec, *this, propertyName, value, shouldThrow)) + return; + + if (shouldThrow) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); +} + char* JSValue::description() const { static const size_t size = 128; diff --git a/Source/JavaScriptCore/runtime/JSValue.h b/Source/JavaScriptCore/runtime/JSValue.h index ce9405817..6e01d8d2d 100644 --- a/Source/JavaScriptCore/runtime/JSValue.h +++ b/Source/JavaScriptCore/runtime/JSValue.h @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2012 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -240,6 +240,7 @@ namespace JSC { JSValue get(ExecState*, unsigned propertyName, PropertySlot&) const; void put(ExecState*, PropertyName, JSValue, PutPropertySlot&); void putToPrimitive(ExecState*, PropertyName, JSValue, PutPropertySlot&); + void putToPrimitiveByIndex(ExecState*, unsigned propertyName, JSValue, bool shouldThrow); void putByIndex(ExecState*, unsigned propertyName, JSValue, bool shouldThrow); JSObject* toThisObject(ExecState*) const; diff --git a/Source/JavaScriptCore/runtime/ObjectPrototype.cpp b/Source/JavaScriptCore/runtime/ObjectPrototype.cpp index 84c60a69c..b1a5b9fb3 100644 --- a/Source/JavaScriptCore/runtime/ObjectPrototype.cpp +++ b/Source/JavaScriptCore/runtime/ObjectPrototype.cpp @@ -74,6 +74,7 @@ void ObjectPrototype::finishCreation(JSGlobalData& globalData, JSGlobalObject*) { Base::finishCreation(globalData); ASSERT(inherits(&s_info)); + notifyUsedAsPrototype(globalData); } bool ObjectPrototype::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot &slot) diff --git a/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp b/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp index ed8aace66..04fea60e8 100644 --- a/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp +++ b/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp @@ -27,7 +27,6 @@ #include "RegExpMatchesArray.h" #include "ButterflyInlineMethods.h" -#include "SparseArrayValueMapInlineMethods.h" namespace JSC { diff --git a/Source/JavaScriptCore/runtime/SparseArrayValueMap.cpp b/Source/JavaScriptCore/runtime/SparseArrayValueMap.cpp index 40c4ed26e..3f709b0a7 100644 --- a/Source/JavaScriptCore/runtime/SparseArrayValueMap.cpp +++ b/Source/JavaScriptCore/runtime/SparseArrayValueMap.cpp @@ -27,11 +27,186 @@ #include "SparseArrayValueMap.h" #include "ClassInfo.h" -#include "SparseArrayValueMapInlineMethods.h" +#include "GetterSetter.h" +#include "JSObject.h" +#include "PropertySlot.h" +#include "Reject.h" +#include "SlotVisitor.h" +#include "Structure.h" namespace JSC { const ClassInfo SparseArrayValueMap::s_info = { "SparseArrayValueMap", 0, 0, 0, CREATE_METHOD_TABLE(SparseArrayValueMap) }; +SparseArrayValueMap::SparseArrayValueMap(JSGlobalData& globalData) + : Base(globalData, globalData.sparseArrayValueMapStructure.get()) + , m_flags(Normal) + , m_reportedCapacity(0) +{ +} + +SparseArrayValueMap::~SparseArrayValueMap() +{ +} + +void SparseArrayValueMap::finishCreation(JSGlobalData& globalData) +{ + Base::finishCreation(globalData); +} + +SparseArrayValueMap* SparseArrayValueMap::create(JSGlobalData& globalData) +{ + SparseArrayValueMap* result = new (NotNull, allocateCell<SparseArrayValueMap>(globalData.heap)) SparseArrayValueMap(globalData); + result->finishCreation(globalData); + return result; +} + +void SparseArrayValueMap::destroy(JSCell* cell) +{ + static_cast<SparseArrayValueMap*>(cell)->SparseArrayValueMap::~SparseArrayValueMap(); +} + +Structure* SparseArrayValueMap::createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) +{ + return Structure::create(globalData, globalObject, prototype, TypeInfo(CompoundType, StructureFlags), &s_info); +} + +SparseArrayValueMap::AddResult SparseArrayValueMap::add(JSObject* array, unsigned i) +{ + SparseArrayEntry entry; + entry.setWithoutWriteBarrier(jsUndefined()); + + AddResult result = m_map.add(i, entry); + size_t capacity = m_map.capacity(); + if (capacity != m_reportedCapacity) { + Heap::heap(array)->reportExtraMemoryCost((capacity - m_reportedCapacity) * (sizeof(unsigned) + sizeof(WriteBarrier<Unknown>))); + m_reportedCapacity = capacity; + } + return result; +} + +void SparseArrayValueMap::putEntry(ExecState* exec, JSObject* array, unsigned i, JSValue value, bool shouldThrow) +{ + AddResult result = add(array, i); + SparseArrayEntry& entry = result.iterator->second; + + // To save a separate find & add, we first always add to the sparse map. + // In the uncommon case that this is a new property, and the array is not + // extensible, this is not the right thing to have done - so remove again. + if (result.isNewEntry && !array->isExtensible()) { + remove(result.iterator); + if (shouldThrow) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); + return; + } + + entry.put(exec, array, this, value, shouldThrow); +} + +bool SparseArrayValueMap::putDirect(ExecState* exec, JSObject* array, unsigned i, JSValue value, unsigned attributes, PutDirectIndexMode mode) +{ + AddResult result = add(array, i); + SparseArrayEntry& entry = result.iterator->second; + + // To save a separate find & add, we first always add to the sparse map. + // In the uncommon case that this is a new property, and the array is not + // extensible, this is not the right thing to have done - so remove again. + if (mode != PutDirectIndexLikePutDirect && result.isNewEntry && !array->isExtensible()) { + remove(result.iterator); + return reject(exec, mode == PutDirectIndexShouldThrow, "Attempting to define property on object that is not extensible."); + } + + entry.attributes = attributes; + entry.set(exec->globalData(), this, value); + return true; +} + +void SparseArrayEntry::get(PropertySlot& slot) const +{ + JSValue value = Base::get(); + ASSERT(value); + + if (LIKELY(!value.isGetterSetter())) { + slot.setValue(value); + return; + } + + JSObject* getter = asGetterSetter(value)->getter(); + if (!getter) { + slot.setUndefined(); + return; + } + + slot.setGetterSlot(getter); +} + +void SparseArrayEntry::get(PropertyDescriptor& descriptor) const +{ + descriptor.setDescriptor(Base::get(), attributes); +} + +JSValue SparseArrayEntry::get(ExecState* exec, JSObject* array) const +{ + JSValue result = Base::get(); + ASSERT(result); + + if (LIKELY(!result.isGetterSetter())) + return result; + + JSObject* getter = asGetterSetter(result)->getter(); + if (!getter) + return jsUndefined(); + + CallData callData; + CallType callType = getter->methodTable()->getCallData(getter, callData); + return call(exec, getter, callType, callData, array, exec->emptyList()); +} + +void SparseArrayEntry::put(ExecState* exec, JSValue thisValue, SparseArrayValueMap* map, JSValue value, bool shouldThrow) +{ + if (!(attributes & Accessor)) { + if (attributes & ReadOnly) { + if (shouldThrow) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); + return; + } + + set(exec->globalData(), map, value); + return; + } + + JSValue accessor = Base::get(); + ASSERT(accessor.isGetterSetter()); + JSObject* setter = asGetterSetter(accessor)->setter(); + + if (!setter) { + if (shouldThrow) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); + return; + } + + CallData callData; + CallType callType = setter->methodTable()->getCallData(setter, callData); + MarkedArgumentBuffer args; + args.append(value); + call(exec, setter, callType, callData, thisValue, args); +} + +JSValue SparseArrayEntry::getNonSparseMode() const +{ + ASSERT(!attributes); + return Base::get(); +} + +void SparseArrayValueMap::visitChildren(JSCell* thisObject, SlotVisitor& visitor) +{ + Base::visitChildren(thisObject, visitor); + + SparseArrayValueMap* thisMap = jsCast<SparseArrayValueMap*>(thisObject); + iterator end = thisMap->m_map.end(); + for (iterator it = thisMap->m_map.begin(); it != end; ++it) + visitor.append(&it->second); +} + } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/SparseArrayValueMap.h b/Source/JavaScriptCore/runtime/SparseArrayValueMap.h index aafdf974f..5d8d0577a 100644 --- a/Source/JavaScriptCore/runtime/SparseArrayValueMap.h +++ b/Source/JavaScriptCore/runtime/SparseArrayValueMap.h @@ -36,6 +36,8 @@ namespace JSC { +class SparseArrayValueMap; + struct SparseArrayEntry : public WriteBarrier<Unknown> { typedef WriteBarrier<Unknown> Base; @@ -44,6 +46,7 @@ struct SparseArrayEntry : public WriteBarrier<Unknown> { JSValue get(ExecState*, JSObject*) const; void get(PropertySlot&) const; void get(PropertyDescriptor&) const; + void put(ExecState*, JSValue thisValue, SparseArrayValueMap*, JSValue, bool shouldThrow); JSValue getNonSparseMode() const; unsigned attributes; diff --git a/Source/JavaScriptCore/runtime/SparseArrayValueMapInlineMethods.h b/Source/JavaScriptCore/runtime/SparseArrayValueMapInlineMethods.h deleted file mode 100644 index f3ef32f46..000000000 --- a/Source/JavaScriptCore/runtime/SparseArrayValueMapInlineMethods.h +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (C) 2011, 2012 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef SparseArrayValueMapInlineMethods_h -#define SparseArrayValueMapInlineMethods_h - -#include "GetterSetter.h" -#include "Reject.h" -#include "SparseArrayValueMap.h" - -namespace JSC { - -inline SparseArrayValueMap::SparseArrayValueMap(JSGlobalData& globalData) - : Base(globalData, globalData.sparseArrayValueMapStructure.get()) - , m_flags(Normal) - , m_reportedCapacity(0) -{ -} - -inline SparseArrayValueMap::~SparseArrayValueMap() -{ -} - -inline void SparseArrayValueMap::finishCreation(JSGlobalData& globalData) -{ - Base::finishCreation(globalData); -} - -inline SparseArrayValueMap* SparseArrayValueMap::create(JSGlobalData& globalData) -{ - SparseArrayValueMap* result = new (NotNull, allocateCell<SparseArrayValueMap>(globalData.heap)) SparseArrayValueMap(globalData); - result->finishCreation(globalData); - return result; -} - -inline void SparseArrayValueMap::destroy(JSCell* cell) -{ - static_cast<SparseArrayValueMap*>(cell)->SparseArrayValueMap::~SparseArrayValueMap(); -} - -inline Structure* SparseArrayValueMap::createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) -{ - return Structure::create(globalData, globalObject, prototype, TypeInfo(CompoundType, StructureFlags), &s_info); -} - -inline SparseArrayValueMap::AddResult SparseArrayValueMap::add(JSObject* array, unsigned i) -{ - SparseArrayEntry entry; - entry.setWithoutWriteBarrier(jsUndefined()); - - AddResult result = m_map.add(i, entry); - size_t capacity = m_map.capacity(); - if (capacity != m_reportedCapacity) { - Heap::heap(array)->reportExtraMemoryCost((capacity - m_reportedCapacity) * (sizeof(unsigned) + sizeof(WriteBarrier<Unknown>))); - m_reportedCapacity = capacity; - } - return result; -} - -inline void SparseArrayValueMap::putEntry(ExecState* exec, JSObject* array, unsigned i, JSValue value, bool shouldThrow) -{ - AddResult result = add(array, i); - SparseArrayEntry& entry = result.iterator->second; - - // To save a separate find & add, we first always add to the sparse map. - // In the uncommon case that this is a new property, and the array is not - // extensible, this is not the right thing to have done - so remove again. - if (result.isNewEntry && !array->isExtensible()) { - remove(result.iterator); - if (shouldThrow) - throwTypeError(exec, StrictModeReadonlyPropertyWriteError); - return; - } - - if (!(entry.attributes & Accessor)) { - if (entry.attributes & ReadOnly) { - if (shouldThrow) - throwTypeError(exec, StrictModeReadonlyPropertyWriteError); - return; - } - - entry.set(exec->globalData(), this, value); - return; - } - - JSValue accessor = entry.SparseArrayEntry::Base::get(); - ASSERT(accessor.isGetterSetter()); - JSObject* setter = asGetterSetter(accessor)->setter(); - - if (!setter) { - if (shouldThrow) - throwTypeError(exec, StrictModeReadonlyPropertyWriteError); - return; - } - - CallData callData; - CallType callType = setter->methodTable()->getCallData(setter, callData); - MarkedArgumentBuffer args; - args.append(value); - call(exec, setter, callType, callData, array, args); -} - -inline bool SparseArrayValueMap::putDirect(ExecState* exec, JSObject* array, unsigned i, JSValue value, unsigned attributes, PutDirectIndexMode mode) -{ - AddResult result = add(array, i); - SparseArrayEntry& entry = result.iterator->second; - - // To save a separate find & add, we first always add to the sparse map. - // In the uncommon case that this is a new property, and the array is not - // extensible, this is not the right thing to have done - so remove again. - if (mode != PutDirectIndexLikePutDirect && result.isNewEntry && !array->isExtensible()) { - remove(result.iterator); - return reject(exec, mode == PutDirectIndexShouldThrow, "Attempting to define property on object that is not extensible."); - } - - entry.attributes = attributes; - entry.set(exec->globalData(), this, value); - return true; -} - -inline void SparseArrayEntry::get(PropertySlot& slot) const -{ - JSValue value = Base::get(); - ASSERT(value); - - if (LIKELY(!value.isGetterSetter())) { - slot.setValue(value); - return; - } - - JSObject* getter = asGetterSetter(value)->getter(); - if (!getter) { - slot.setUndefined(); - return; - } - - slot.setGetterSlot(getter); -} - -inline void SparseArrayEntry::get(PropertyDescriptor& descriptor) const -{ - descriptor.setDescriptor(Base::get(), attributes); -} - -inline JSValue SparseArrayEntry::get(ExecState* exec, JSObject* array) const -{ - JSValue result = Base::get(); - ASSERT(result); - - if (LIKELY(!result.isGetterSetter())) - return result; - - JSObject* getter = asGetterSetter(result)->getter(); - if (!getter) - return jsUndefined(); - - CallData callData; - CallType callType = getter->methodTable()->getCallData(getter, callData); - return call(exec, getter, callType, callData, array, exec->emptyList()); -} - -inline JSValue SparseArrayEntry::getNonSparseMode() const -{ - ASSERT(!attributes); - return Base::get(); -} - -inline void SparseArrayValueMap::visitChildren(JSCell* thisObject, SlotVisitor& visitor) -{ - Base::visitChildren(thisObject, visitor); - - SparseArrayValueMap* thisMap = jsCast<SparseArrayValueMap*>(thisObject); - iterator end = thisMap->m_map.end(); - for (iterator it = thisMap->m_map.begin(); it != end; ++it) - visitor.append(&it->second); -} - -} // namespace JSC - -#endif // SparseArrayValueMapInlineMethods_h - diff --git a/Source/JavaScriptCore/runtime/Structure.cpp b/Source/JavaScriptCore/runtime/Structure.cpp index c99c6dda4..a59a0860d 100644 --- a/Source/JavaScriptCore/runtime/Structure.cpp +++ b/Source/JavaScriptCore/runtime/Structure.cpp @@ -309,6 +309,30 @@ Structure* Structure::addPropertyTransitionToExistingStructure(Structure* struct return 0; } +bool Structure::anyObjectInChainMayInterceptIndexedAccesses() const +{ + for (const Structure* current = this; ;) { + if (current->mayInterceptIndexedAccesses()) + return true; + + JSValue prototype = current->storedPrototype(); + if (prototype.isNull()) + return false; + + current = asObject(prototype)->structure(); + } +} + +NonPropertyTransition Structure::suggestedIndexingTransition() const +{ + ASSERT(!hasIndexedProperties(indexingType())); + + if (anyObjectInChainMayInterceptIndexedAccesses() || globalObject()->isHavingABadTime()) + return AllocateSlowPutArrayStorage; + + return AllocateArrayStorage; +} + Structure* Structure::addPropertyTransition(JSGlobalData& globalData, Structure* structure, PropertyName propertyName, unsigned attributes, JSCell* specificValue, PropertyOffset& offset) { // If we have a specific function, we may have got to this point if there is diff --git a/Source/JavaScriptCore/runtime/Structure.h b/Source/JavaScriptCore/runtime/Structure.h index 9303a0dbb..e77287b20 100644 --- a/Source/JavaScriptCore/runtime/Structure.h +++ b/Source/JavaScriptCore/runtime/Structure.h @@ -144,7 +144,16 @@ namespace JSC { IndexingType indexingType() const { return m_indexingType & AllArrayTypes; } IndexingType indexingTypeIncludingHistory() const { return m_indexingType; } - + + bool mayInterceptIndexedAccesses() const + { + return !!(indexingTypeIncludingHistory() & MayHaveIndexedAccessors); + } + + bool anyObjectInChainMayInterceptIndexedAccesses() const; + + NonPropertyTransition suggestedIndexingTransition() const; + JSGlobalObject* globalObject() const { return m_globalObject.get(); } void setGlobalObject(JSGlobalData& globalData, JSGlobalObject* globalObject) { m_globalObject.set(globalData, this, globalObject); } diff --git a/Source/JavaScriptCore/runtime/StructureTransitionTable.h b/Source/JavaScriptCore/runtime/StructureTransitionTable.h index 59e7e94f3..90cb6a4db 100644 --- a/Source/JavaScriptCore/runtime/StructureTransitionTable.h +++ b/Source/JavaScriptCore/runtime/StructureTransitionTable.h @@ -43,7 +43,10 @@ static const unsigned FirstInternalAttribute = 1 << 6; // Use for transitions th // Support for attributes used to indicate transitions not related to properties. // If any of these are used, the string portion of the key should be 0. enum NonPropertyTransition { - AllocateArrayStorage + AllocateArrayStorage, + AllocateSlowPutArrayStorage, + SwitchToSlowPutArrayStorage, + AddIndexedAccessors }; inline unsigned toAttributes(NonPropertyTransition transition) @@ -56,6 +59,13 @@ inline IndexingType newIndexingType(IndexingType oldType, NonPropertyTransition switch (transition) { case AllocateArrayStorage: return oldType | HasArrayStorage; + case AllocateSlowPutArrayStorage: + return oldType | HasSlowPutArrayStorage; + case SwitchToSlowPutArrayStorage: + ASSERT(oldType & HasArrayStorage); + return (oldType & ~HasArrayStorage) | HasSlowPutArrayStorage; + case AddIndexedAccessors: + return oldType | MayHaveIndexedAccessors; default: ASSERT_NOT_REACHED(); return oldType; diff --git a/Source/JavaScriptCore/runtime/SymbolTable.h b/Source/JavaScriptCore/runtime/SymbolTable.h index f6f70c6b9..5427a009b 100644 --- a/Source/JavaScriptCore/runtime/SymbolTable.h +++ b/Source/JavaScriptCore/runtime/SymbolTable.h @@ -40,6 +40,23 @@ namespace JSC { class Watchpoint; class WatchpointSet; + struct SlowArgument { + enum Status { + Normal = 0, + Captured = 1, + Deleted = 2 + }; + + SlowArgument() + : status(Normal) + , indexIfCaptured(0) + { + } + + Status status; + int indexIfCaptured; // If status is 'Captured', indexIfCaptured is our index in the CallFrame. + }; + static ALWAYS_INLINE int missingSymbolMarker() { return std::numeric_limits<int>::max(); } // The bit twiddling in this class assumes that every register index is a @@ -357,9 +374,14 @@ namespace JSC { int captureEnd() { return m_captureEnd; } void setCaptureEnd(int captureEnd) { m_captureEnd = captureEnd; } + int parameterCount() { return m_parameterCountIncludingThis - 1; } int parameterCountIncludingThis() { return m_parameterCountIncludingThis; } void setParameterCountIncludingThis(int parameterCountIncludingThis) { m_parameterCountIncludingThis = parameterCountIncludingThis; } + // 0 if we don't capture any arguments; parameterCount() in length if we do. + const SlowArgument* slowArguments() { return m_slowArguments.get(); } + void setSlowArguments(PassOwnArrayPtr<SlowArgument> slowArguments) { m_slowArguments = slowArguments; } + static JS_EXPORTDATA const ClassInfo s_info; private: @@ -379,8 +401,9 @@ namespace JSC { CaptureMode m_captureMode; int m_captureStart; int m_captureEnd; + + OwnArrayPtr<SlowArgument> m_slowArguments; }; - } // namespace JSC #endif // SymbolTable_h |